﻿#include "YImageDrawer.h"
#include <QVector>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QGraphicsProxyWidget>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsSceneMouseEvent>
#include <QMouseEvent>
#include <QTimer>
#include <QtMath>
#include <QPlainTextEdit>
#include <QStyle>
#include <QScrollBar>
#include "DrawTools.h"
#include "Yuan.h"
// add by liq 11
#include <QGraphicsPixmapItem>
#include <QMenu>
//#include <QUndoCommand>
#include "Commands.h"

// add by liq test
#include <QMessageBox>
//#include <QUndoView>

#include <QDebug>
#define DP qDebug()
#define DF DP << __func__

// 默认贴图快捷键
static QString PIN_KEY = "F7";
QPoint screenShotRect(0,0);

namespace Y_Image_Drawer_GUI {
class YGraphicsChangeItem;
//class YGraphicsItem
//{
//public:
//    virtual ~YGraphicsItem(){}
//    virtual void rerect(const QRect& rect) {Q_UNUSED(rect);}
//    virtual void rerect(const QPoint& pos){
//        if(lastPos == pos) return;
//        lastPos = pos;
//        QRect rect;
//        rect.setX(qMin(startPos.x(), pos.x()));
//        rect.setY(qMin(startPos.y(), pos.y()));
//        rect.setRight(qMax(startPos.x(), pos.x()));
//        rect.setBottom(qMax(startPos.y(), pos.y()));
//        rerect(rect);
//    }
//    virtual void reChangePos(){}
//    virtual void showChange(){}
//    virtual void hideChange(){}
//    virtual void cursorChange(const QPointF&, YGraphicsChangeItem*){}
//    bool inChangeHover();
//public:
//    YImageDrawer::Type itemType;
//    QPoint startPos;
//    QPoint lastPos;
//    QVector<QPointF> changePos;
//    QList<YGraphicsChangeItem*> changeItem;
//    bool showChanged = false;
//    bool inChangeArea = false;
//    char AlignPadding[6];
//    QPointF pressPos;
//    int resizeType = 0;//0:移动,1:垂直水平,2:垂直,3:水平
//    char AlignPadding2[4];
//    YGraphicsChangeItem* cursorItem = nullptr;
//    bool activeWindowFocus = false;
//    int currentThickness;
//    QColor currentColor;

//};

DiagramScene::DiagramScene(QRect rect, QObject *parent)
    : QGraphicsScene(parent)
{}

void DiagramScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    QPointF mousePos(event->buttonDownScenePos(Qt::LeftButton).x(),
                     event->buttonDownScenePos(Qt::LeftButton).y());
    const QList<QGraphicsItem *> itemList = items(mousePos);
    movingItem = itemList.isEmpty() ? nullptr : itemList.first();
    if(movingItem == nullptr){
        if(this->focusItem() != nullptr){
            movingItem = this->focusItem();
        }else{
            movingItem = nullptr;
        }
    }

    if (movingItem != nullptr && event->button() == Qt::LeftButton){
        oldPos = movingItem->pos();
//        oldSize = movingItem->boundingRect().size();
        // 不能添加此判断，否则箭头点击时条件不满足
//        if(this->focusItem() != nullptr){
            YGraphicsItem* yitem = dynamic_cast<YGraphicsItem*>(movingItem);
            if(yitem != nullptr){
                yitem->oldWidth = movingItem->boundingRect().width();
                yitem->oldHeight = movingItem->boundingRect().height();
                if(yitem->itemType == YImageDrawer::Arrow){
//                    oldLastPos = dynamic_cast<YGraphicsItem*>(movingItem)->lastPos;
                    oldLastPos = yitem->lastPos;
                    yitem->oldPos = movingItem->pos();
                    yitem->oldLastPos = yitem->lastPos;
                }else if(yitem->itemType == YImageDrawer::Rect){
                    yitem->oldPos = movingItem->pos();
                    yitem->oldLastPos = yitem->lastPos;
                    QGraphicsRectItem* rectItem = dynamic_cast<QGraphicsRectItem*>(movingItem);
                    yitem->oldRect = rectItem->rect();
                }else if(yitem->itemType == YImageDrawer::Ellipse){
                    yitem->oldPos = movingItem->pos();
                    yitem->oldLastPos = yitem->lastPos;
                    QGraphicsEllipseItem* rectItem = dynamic_cast<QGraphicsEllipseItem*>(movingItem);
                    yitem->oldRect = rectItem->rect();
                }
            }
//        }
    }
    QGraphicsScene::mousePressEvent(event);
}

void DiagramScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    if (movingItem != nullptr && event->button() == Qt::LeftButton) {
        if(this->focusItem() != nullptr){
            // 保存此时元素位置，用于后续方向键压下时移动恢复
            keyPressOldPos = this->focusItem()->pos();
//            keyPressOldLastPos = dynamic_cast<YGraphicsItem*>(this->focusItem())->lastPos;
            YGraphicsItem* yitem = dynamic_cast<YGraphicsItem*>(this->focusItem());
            if(yitem != nullptr && yitem->itemType == YImageDrawer::Arrow){
                keyPressOldLastPos = yitem->lastPos;
            }
            keyPressMovingItem = this->focusItem();

            // undo/redo
            if (oldPos != movingItem->pos() && !oldPos.isNull()){
                emit sigItemMoved(movingItem, oldPos, oldLastPos);
            }

//            // undo/redo
            // 此处resize时无法触发
//            if (oldWidth != movingItem->boundingRect().width() || oldHeight != movingItem->boundingRect().height()){
//                emit sigItemSizeChanged(movingItem, QSizeF(width, height));
//            }
        }
        movingItem = nullptr;
    }
    QGraphicsScene::mouseReleaseEvent(event);
}

void DiagramScene::keyPressEvent(QKeyEvent *event) {
    // 添加isAutoRepeat判断，防止长按时连续触发本事件
    if(!event->isAutoRepeat()){
        if (event->key() == Qt::Key_Z) {
            if(event->modifiers() & Qt::ControlModifier){
                emit sigDoUndoAction();
            }
        }else if (event->key() == Qt::Key_Y) {
            if(event->modifiers() & Qt::ControlModifier){
                emit sigDoRedoAction();
            }
        }
        // 不能在此获取oldPos，否则undo/redo时会执行多步，不能一步到位
        else if (event->key() == Qt::Key_Left || event->key() == Qt::Key_Right || event->key() == Qt::Key_Up || event->key() == Qt::Key_Down){
            if(keyPressMovingItem == nullptr && this->focusItem() != nullptr){
                keyPressOldPos = this->focusItem()->pos();
                YGraphicsItem* yitem = dynamic_cast<YGraphicsItem*>(this->focusItem());
                if(yitem != nullptr && yitem->itemType == YImageDrawer::Arrow){
                    keyPressOldLastPos = yitem->lastPos;
                }
                keyPressMovingItem = this->focusItem();
            }
        }
    }
    QGraphicsScene::keyPressEvent(event);
}

void DiagramScene::keyReleaseEvent(QKeyEvent *event){
    // 添加isAutoRepeat判断，防止长按时连续触发本事件
    if(!event->isAutoRepeat()){
        if (event->key() == Qt::Key_Left || event->key() == Qt::Key_Right || event->key() == Qt::Key_Up || event->key() == Qt::Key_Down){
            if(keyPressMovingItem != nullptr){
                if(keyPressOldPos != keyPressMovingItem->pos() && !keyPressOldPos.isNull()){
                    emit sigItemMoved(keyPressMovingItem, keyPressOldPos, keyPressOldLastPos);
                }
                keyPressMovingItem = nullptr;
            }
        }
    }
    QGraphicsScene::keyReleaseEvent(event);
}

class YGraphicsChangeItem: public QGraphicsEllipseItem{
public:
    YGraphicsChangeItem():QGraphicsEllipseItem(QRect(-3, -3, 6, 6)){setBrush(Qt::white);setAcceptHoverEvents(true);}
    bool isHover = false;
    char AlignPadding[7];
    YGraphicsItem* item;
    QPointF pressPos;
    void hoverEnterEvent(QGraphicsSceneHoverEvent *){isHover = true;scene()->setProperty("inChangeArea", true);}
    void hoverLeaveEvent(QGraphicsSceneHoverEvent *){isHover = false;scene()->setProperty("inChangeArea", false);}
    void mousePressEvent(QGraphicsSceneMouseEvent *event){item->cursorChange(event->pos() + pos(), this);}
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event){item->cursorChange(event->pos() + pos(), this);}
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *){item->cursorChange(QPointF(), nullptr);}
};
bool YGraphicsItem::inChangeHover(){
    for(YGraphicsChangeItem* item : changeItem){
        if(item->isHover) return true;
    }
    return false;
}
class YGraphicsRectItem : public QGraphicsRectItem, public YGraphicsItem
{
public:
    void rerect(const QRect& rect){
        if(changePos.empty()){
            changePos.resize(8);
        }
        setPos(rect.topLeft());
        if(!isShiftKeyPressed){
            setRect(QRectF(0, 0, rect.width(), rect.height()));
        }else{
            int maxVal = qMax(rect.width(), rect.height());
            setRect(QRectF(0, 0, maxVal, maxVal));
        }
    }
    std::function<void()> fun_ptr_reChangePos =  std::bind(&YGraphicsRectItem::reChangePos, this);
    void reChangePos(){
        QRectF rect(pos(), this->rect().size());
        changePos[0] = rect.topLeft();
        changePos[1] = rect.topRight();
        changePos[2] = rect.bottomLeft();
        changePos[3] = rect.bottomRight();
        changePos[4] = QPointF(rect.x() + rect.width() / 2.0, rect.y());
        changePos[5] = QPointF(rect.x() + rect.width() / 2.0, rect.bottom());
        changePos[6] = QPointF(rect.x(), rect.y() + rect.height() / 2.0);
        changePos[7] = QPointF(rect.right(), rect.y() + rect.height() / 2.0);
    }
    void showChange(){
        static QCursor cursors[8] = {Qt::SizeFDiagCursor, Qt::SizeBDiagCursor, Qt::SizeBDiagCursor, Qt::SizeFDiagCursor,
                                     Qt::SizeVerCursor, Qt::SizeVerCursor, Qt::SizeHorCursor, Qt::SizeHorCursor};
        if(changeItem.empty()){
            for(int i = 0; i < changePos.size(); ++i){
                YGraphicsChangeItem* ellipse = new YGraphicsChangeItem;
                changeItem.append(ellipse);
                ellipse->setCursor(cursors[i]);
                ellipse->item = this;
                scene()->addItem(ellipse);
            }
        }
        reChangePos();
        for(int i = 0; i < changePos.size(); ++i){
            changeItem[i]->setPos(changePos.at(i));
            QPen pen = this->pen();
            pen.setWidth(1);
            changeItem[i]->setPen(pen);
            changeItem[i]->show();
        }
        showChanged = true;
    }
    void hideChange(){
        for(int i = 0; i < changePos.size(); ++i){
            changeItem[i]->hide();
        }
        showChanged = false;
    }
    void cursorChange(const QPointF& cursorPressPos, YGraphicsChangeItem* cursorItem){
        if(this->cursorItem){
            if(cursorItem == this->cursorItem){
                QPoint mapCursorPressPos = cursorPressPos.toPoint();
                if(resizeType == 1){
                    YGraphicsItem::rerect(mapCursorPressPos);
                }else if(resizeType == 2){
                    if(lastPos.y() == mapCursorPressPos.y()) return;
                    lastPos = mapCursorPressPos;
                    QRect rect;
                    rect.setX(qMin(pos().toPoint().x(), startPos.x()));
                    rect.setY(qMin(startPos.y(), mapCursorPressPos.y()));
                    rect.setRight(qMax(pos().toPoint().x(), startPos.x()));
                    rect.setBottom(qMax(startPos.y(), mapCursorPressPos.y()));
                    rerect(rect);
                }else{
                    if(lastPos.x() == mapCursorPressPos.x()) return;
                    lastPos = mapCursorPressPos;
                    QRect rect;
                    rect.setX(qMin(startPos.x(), mapCursorPressPos.x()));
                    rect.setY(qMin(pos().toPoint().y(), startPos.y()));
                    rect.setRight(qMax(startPos.x(), mapCursorPressPos.x()));
                    rect.setBottom(qMax(pos().toPoint().y(), startPos.y()));
                    rerect(rect);
                }
                showChange();
            }else{
                resizeType = 0;
                this->cursorItem = nullptr;
                setFocus();
            }
        }else{
            this->cursorItem = cursorItem;
            int index = changeItem.indexOf(cursorItem);
            if(index < 4) resizeType = 1;
            else if(index < 6) resizeType = 2;
            else resizeType = 3;
            QRect rect = QRectF(pos(), this->rect().size()).toRect();
            switch(index){
            case 0: startPos = rect.bottomRight();break;
            case 1: startPos = rect.bottomLeft();break;
            case 2: startPos = rect.topRight();break;
            case 3: startPos = rect.topLeft();break;
            case 4: startPos = rect.bottomRight();break;
            case 5: startPos = rect.topRight();break;
            case 6: startPos = rect.bottomRight();break;
            case 7: startPos = rect.bottomLeft();break;
            }
        }
    }
    explicit YGraphicsRectItem(const QPointF &pos, const QSizeF& size, bool shiftKeyPressed): QGraphicsRectItem(QRectF(QPointF(0, 0), size)){
        isShiftKeyPressed = shiftKeyPressed;
        itemType = YImageDrawer::Rect;
        setPos(pos);
        setAcceptHoverEvents(true);
        setBrush(Qt::NoBrush);
        setFlag(QGraphicsItem::ItemIsFocusable);
        // add by liq 13
        setFlag(QGraphicsItem::ItemIsSelectable);
    }
    virtual void focusInEvent(QFocusEvent *){
        showChange();
        // add by liq 13
        setSelected(true);
        isShiftKeyPressed = false;
    }
    virtual void focusOutEvent(QFocusEvent *){
        if(!inChangeHover()){
            hideChange();
            // add by liq 13
            setSelected(false);
        }
    }
    virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event){
        QPointF epos = event->pos();
        bool xValid = ((epos.x() >= rect().x() && epos.x() <= rect().x() + pen().width()) ||
                       (epos.x() <= rect().right() && epos.x() >= rect().right() - pen().width()));
        bool yValid = ((epos.y() >= rect().y() && epos.y() <= rect().y() + pen().width()) ||
                       (epos.y() <= rect().bottom() && epos.y() >= rect().bottom() - pen().width()));
        inChangeArea = (xValid || yValid);
        scene()->setProperty("inChangeArea", inChangeArea);
        if(inChangeArea){
            setCursor(Qt::SizeAllCursor);
        }else{
            unsetCursor();
        }
    }
    virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *){
        inChangeArea = false;
        scene()->setProperty("inChangeArea", inChangeArea);
        unsetCursor();
    }
    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event){
        pressPos = event->pos();
        hideChange();
    }
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event){
        if(inChangeArea){
            if(resizeType == 0){
                QPointF pos = this->pos() - pressPos + event->pos();
                setPos(pos);
            }
        }
    }
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *){if(inChangeArea){reChangePos();showChange();}}
    // add by liq 13 start
    virtual void keyPressEvent(QKeyEvent *event){
        int left = 0, top = 0, right = 0, bottom = 0;
        if(event->key() == Qt::Key_Left){
            left = -1;
        }else if(event->key() == Qt::Key_Right){
            right = 1;
        }else if(event->key() == Qt::Key_Up){
            top = -1;
        }else if(event->key() == Qt::Key_Down){
            bottom = 1;
        }else if(event->key() == Qt::Key_Delete){
            // 此处接收到的事件无法传给scene，也无法通过signals传递，因为item不是QObject，通过scene的eventFilter过滤
//            event->ignore();
//            return;
        }else if(event->key() == Qt::Key_Shift){
            isShiftKeyPressed = true;
            return;
        }
        QPointF newPos(this->pos().x() + left + right, this->pos().y() + top + bottom);
        setPos(newPos);
        showChange();
        QGraphicsItem::keyPressEvent(event);
    }
    virtual void keyReleaseEvent(QKeyEvent *event){
        if(event->key() == Qt::Key_Shift){
            isShiftKeyPressed = false;
        }
        QGraphicsItem::keyReleaseEvent(event);
    }
    // add by liq 13 end
    bool isShiftKeyPressed = false;
};
class YGraphicsEllipseItem : public QGraphicsEllipseItem, public YGraphicsItem
{
public:
    void rerect(const QRect& rect){
        if(changePos.empty()){
//            changePos.resize(4);
            changePos.resize(8);
        }
        setPos(rect.topLeft());
        if(!isShiftKeyPressed){
            setRect(QRectF(0, 0, rect.width(), rect.height()));
        }else{
            int maxVal = qMax(rect.width(), rect.height());
            setRect(QRectF(0, 0, maxVal, maxVal));
        }
    }
    std::function<void()> fun_ptr_reChangePos =  std::bind(&YGraphicsEllipseItem::reChangePos, this);
    void reChangePos(){
        QRectF rect(pos(), this->rect().size());
//        changePos[0] = QPointF(rect.x() + rect.width() / 2.0, rect.y());
//        changePos[1] = QPointF(rect.x() + rect.width() / 2.0, rect.bottom());
//        changePos[2] = QPointF(rect.x(), rect.y() + rect.height() / 2.0);
//        changePos[3] = QPointF(rect.right(), rect.y() + rect.height() / 2.0);
        changePos[0] = rect.topLeft();
        changePos[1] = rect.topRight();
        changePos[2] = rect.bottomLeft();
        changePos[3] = rect.bottomRight();
        changePos[4] = QPointF(rect.x() + rect.width() / 2.0, rect.y());
        changePos[5] = QPointF(rect.x() + rect.width() / 2.0, rect.bottom());
        changePos[6] = QPointF(rect.x(), rect.y() + rect.height() / 2.0);
        changePos[7] = QPointF(rect.right(), rect.y() + rect.height() / 2.0);
    }
    void showChange(){
//        static QCursor cursors[4] = {Qt::SizeVerCursor, Qt::SizeVerCursor, Qt::SizeHorCursor, Qt::SizeHorCursor};
        static QCursor cursors[8] = {Qt::SizeFDiagCursor, Qt::SizeBDiagCursor, Qt::SizeBDiagCursor, Qt::SizeFDiagCursor,
                                     Qt::SizeVerCursor, Qt::SizeVerCursor, Qt::SizeHorCursor, Qt::SizeHorCursor};
        if(changeItem.empty()){
            for(int i = 0; i < changePos.size(); ++i){
                YGraphicsChangeItem* ellipse = new YGraphicsChangeItem;
                changeItem.append(ellipse);
                ellipse->setCursor(cursors[i]);
                ellipse->item = this;
                scene()->addItem(ellipse);
            }
        }
        reChangePos();
        for(int i = 0; i < changePos.size(); ++i){
            changeItem[i]->setPos(changePos.at(i));
            QPen pen = this->pen();
            pen.setWidth(1);
            changeItem[i]->setPen(pen);
            changeItem[i]->show();
        }
        showChanged = true;
    }
    void hideChange(){
        for(int i = 0; i < changePos.size(); ++i){
            changeItem[i]->hide();
        }
        showChanged = false;
    }
    void cursorChange(const QPointF& cursorPressPos, YGraphicsChangeItem* cursorItem){
        if(this->cursorItem){
            if(cursorItem == this->cursorItem){
                QPoint mapCursorPressPos = cursorPressPos.toPoint();
                if(resizeType == 1){
                    YGraphicsItem::rerect(mapCursorPressPos);
                }else if(resizeType == 2){
                    if(lastPos.y() == mapCursorPressPos.y()) return;
                    lastPos = mapCursorPressPos;
                    QRect rect;
                    rect.setX(qMin(pos().toPoint().x(), startPos.x()));
                    rect.setY(qMin(startPos.y(), mapCursorPressPos.y()));
                    rect.setRight(qMax(pos().toPoint().x(), startPos.x()));
                    rect.setBottom(qMax(startPos.y(), mapCursorPressPos.y()));
                    rerect(rect);
                }else{
                    if(lastPos.x() == mapCursorPressPos.x()) return;
                    lastPos = mapCursorPressPos;
                    QRect rect;
                    rect.setX(qMin(startPos.x(), mapCursorPressPos.x()));
                    rect.setY(qMin(pos().toPoint().y(), startPos.y()));
                    rect.setRight(qMax(startPos.x(), mapCursorPressPos.x()));
                    rect.setBottom(qMax(pos().toPoint().y(), startPos.y()));
                    rerect(rect);
                }
                showChange();
            }else{
                resizeType = 0;
                this->cursorItem = nullptr;
                setFocus();
            }
        }else{
            this->cursorItem = cursorItem;
            int index = changeItem.indexOf(cursorItem);
//            if(index < 2) resizeType = 2;
//            else resizeType = 3;
            if(index < 4) resizeType = 1;
            else if(index < 6) resizeType = 2;
            else resizeType = 3;
            QRect rect = QRectF(pos(), this->rect().size()).toRect();
            switch(index){
//            case 0: startPos = rect.bottomRight();break;
//            case 1: startPos = rect.topRight();break;
//            case 2: startPos = rect.bottomRight();break;
//            case 3: startPos = rect.bottomLeft();break;
            case 0: startPos = rect.bottomRight();break;
            case 1: startPos = rect.bottomLeft();break;
            case 2: startPos = rect.topRight();break;
            case 3: startPos = rect.topLeft();break;
            case 4: startPos = rect.bottomRight();break;
            case 5: startPos = rect.topRight();break;
            case 6: startPos = rect.bottomRight();break;
            case 7: startPos = rect.bottomLeft();break;
            }
        }
    }
    explicit YGraphicsEllipseItem(const QPointF &pos, const QSizeF& size, bool shiftKeyPressed): QGraphicsEllipseItem(QRectF(QPointF(0, 0), size)){
        isShiftKeyPressed = shiftKeyPressed;
        itemType = YImageDrawer::Ellipse;
        setPos(pos);
        setAcceptHoverEvents(true);
        setBrush(Qt::NoBrush);
        setFlag(QGraphicsItem::ItemIsFocusable);
        // add by liq 13
        setFlag(QGraphicsItem::ItemIsSelectable);
    }
    virtual void focusInEvent(QFocusEvent *){
        showChange();
        // add by liq 13
        setSelected(true);
        isShiftKeyPressed = false;
    }
    virtual void focusOutEvent(QFocusEvent *){
        if(!inChangeHover()){
            hideChange();
            // add by liq 13
            setSelected(false);
        }
    }
    virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event){
        QPointF epos = event->pos();
        QPainterPath path = shape();
        inChangeArea = (path.contains(epos) &&
                        !path.contains(QRectF(epos.x() - pen().width(), epos.y() - pen().width(),
                                              pen().width() + 1, pen().width() + 1)));
        scene()->setProperty("inChangeArea", inChangeArea);
        if(inChangeArea){
            setCursor(Qt::SizeAllCursor);
        }else{
            unsetCursor();
        }
    }
    virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *){
        inChangeArea = false;
        scene()->setProperty("inChangeArea", inChangeArea);
        unsetCursor();
    }
    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event){
        pressPos = event->pos();
        hideChange();
    }
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event){
        if(inChangeArea){
            if(resizeType == 0){
                QPointF pos = this->pos() - pressPos + event->pos();
                setPos(pos);
            }
        }
    }
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *){if(inChangeArea){reChangePos();showChange();}}
    // add by liq 13 start
    virtual void keyPressEvent(QKeyEvent *event){
        int left = 0, top = 0, right = 0, bottom = 0;
        if(event->key() == Qt::Key_Left){
            left = -1;
        }else if(event->key() == Qt::Key_Right){
            right = 1;
        }else if(event->key() == Qt::Key_Up){
            top = -1;
        }else if(event->key() == Qt::Key_Down){
            bottom = 1;
        }else if(event->key() == Qt::Key_Delete){
               // 此处接收到的事件无法传给scene，也无法通过signals传递，因为item不是QObject，通过scene的eventFilter过滤
//            event->ignore();
//            return;
        }else if(event->key() == Qt::Key_Shift){
            isShiftKeyPressed = true;
            return;
        }
        QPointF newPos(this->pos().x() + left + right, this->pos().y() + top + bottom);
        setPos(newPos);
        showChange();
        QGraphicsItem::keyPressEvent(event);
    }
    virtual void keyReleaseEvent(QKeyEvent *event){
        if(event->key() == Qt::Key_Shift){
            isShiftKeyPressed = false;
        }
        QGraphicsItem::keyReleaseEvent(event);
    }
    // add by liq 13 end
    bool isShiftKeyPressed = false;
};
class YGraphicsArrowItem : public QGraphicsPolygonItem, public YGraphicsItem
{
public:
    virtual void rerect(const QPoint& pos){
        if(lastPos == pos) return;
        if(!isShiftKeyPressed){
            lastPos = pos;
        }else{
            if(qAbs(pos.x() - this->pos().x()) > qAbs(pos.y() - this->pos().y())){
                lastPos = QPoint(pos.x(), this->pos().y());
            }else if(qAbs(pos.x() - this->pos().x()) < qAbs(pos.y() - this->pos().y())){
                lastPos = QPoint(this->pos().x(), pos.y());
            }else{
                lastPos = QPoint(pos.x(), pos.y());
            }
        }
        makePath();
    }
    QPoint rotatePoint(const QPoint& pos, qreal cosTheta, qreal sinTheta, int positiveX, int positiveY)
    {
        return QPoint(qRound(pos.x() * cosTheta + pos.y() * sinTheta) * positiveX,
                      qRound(-pos.x() * sinTheta + pos.y() * cosTheta) * positiveY);
    }
    char AlignPadding_YGraphicsArrowItem[7];
    QVector<QPoint> points;
    std::function<void()> fun_ptr_makePath =  std::bind(&YGraphicsArrowItem::makePath, this);
    std::function<void()> fun_ptr_showChange =  std::bind(&YGraphicsArrowItem::showChange, this);
    void makePath(){
        QPoint pos = this->pos().toPoint();
        int x = qAbs(lastPos.x() - pos.x());
        int y = qAbs(lastPos.y() - pos.y());
        qreal rwidth = qSqrt(x*x+y*y), theta = qAcos(x / rwidth);
        int width = qRound(rwidth);
        int grade = pen().width();
        qreal cosTheta = qCos(theta);
        qreal sinTheta = qSin(theta);
        int positiveX = (lastPos.x() >= pos.x() ? 1 : -1), positiveY = (lastPos.y() <= pos.y() ? 1 : -1);

        int size = 11;
        if(width >= 30 && grade > 1) size = 15;
        if(width >= 40 && grade > 2) size = 21;

        if(points.size() != 6) points.resize(6);

        int wp = width - size, ah = size / 2, wh = ah / 2;
        points[3] = rotatePoint(QPoint(width, 0), cosTheta, sinTheta, positiveX, positiveY);
        points[1] = rotatePoint(QPoint(wp, -wh), cosTheta, sinTheta, positiveX, positiveY);
        points[2] = rotatePoint(QPoint(wp, -ah), cosTheta, sinTheta, positiveX, positiveY);
        points[4] = rotatePoint(QPoint(wp, ah), cosTheta, sinTheta, positiveX, positiveY);
        points[5] = rotatePoint(QPoint(wp, wh), cosTheta, sinTheta, positiveX, positiveY);
        setPolygon(QPolygon(points));
    }
    void reChangePos(){
        changePos[0] = pos();
        changePos[1] = QPointF(lastPos);
    }
    void showChange(){
        static QCursor cursors[2] = {Qt::SizeFDiagCursor, Qt::SizeBDiagCursor};
        if(changePos.empty()){
            changePos.resize(2);
        }
        if(changeItem.empty()){
            for(int i = 0; i < changePos.size(); ++i){
                YGraphicsChangeItem* ellipse = new YGraphicsChangeItem;
                changeItem.append(ellipse);
                ellipse->setCursor(cursors[i]);
                ellipse->item = this;
                scene()->addItem(ellipse);
            }
        }
        reChangePos();
        for(int i = 0; i < changePos.size(); ++i){
            changeItem[i]->setPos(changePos.at(i));
            changeItem[i]->setPen(QPen(brush().color(), 1));
            changeItem[i]->show();
        }
        showChanged = true;
    }
    void hideChange(){
        for(int i = 0; i < changePos.size(); ++i){
            changeItem[i]->hide();
        }
        showChanged = false;
    }
    void cursorChange(const QPointF& cursorPressPos, YGraphicsChangeItem* cursorItem){
        if(this->cursorItem){
            if(cursorItem == this->cursorItem){
                QPoint mapCursorPressPos = cursorPressPos.toPoint();
                if(resizeType == 1){
                    if(cursorPressPos == pos()) return;
                    setPos(cursorPressPos);
                    makePath();
                }else{
                    if(mapCursorPressPos == lastPos) return;

                    if(!isShiftKeyPressed){
                        lastPos = mapCursorPressPos;
                    }else{
                        if(qAbs(QPointF(cursorPressPos).x() - pos().x()) > qAbs(QPointF(cursorPressPos).y() - pos().y())){
                            lastPos = QPoint(QPointF(cursorPressPos).x(), pos().y());
                        }else if(qAbs(QPointF(cursorPressPos).x() - pos().x()) < qAbs(QPointF(cursorPressPos).y() - pos().y())){
                            lastPos = QPoint(pos().x(), QPointF(cursorPressPos).y());
                        }else{
                            lastPos = QPoint(QPointF(cursorPressPos).x(), QPointF(cursorPressPos).y());
                        }
//                        double x = QPointF(cursorPressPos).x() - pos().x();
//                        double y = QPointF(cursorPressPos).y() - pos().y();
//                        double k = qAbs(y) / qAbs(x);
//                        if(k > 2){
//                            lastPos = QPoint(pos().x(), QPointF(cursorPressPos).y());
//                        }else if(k < 0.5){
//                            lastPos = QPoint(QPointF(cursorPressPos).x(), pos().y());
//                        }else{
//                            if(qAbs(y) >= qAbs(x)){
//                                if(y > 0){
//                                    if(x > 0){
//                                        lastPos = QPoint(QPointF(cursorPressPos).y(), QPointF(cursorPressPos).y());
//                                    }else{
//                                        lastPos = QPoint(-QPointF(cursorPressPos).y(), QPointF(cursorPressPos).y());
//                                    }
//                                }else{
//                                    if(x > 0){
//                                        lastPos = QPoint(QPointF(cursorPressPos).y(), -QPointF(cursorPressPos).y());
//                                    }else{
//                                        lastPos = QPoint(-QPointF(cursorPressPos).y(), -QPointF(cursorPressPos).y());
//                                    }
//                                }
//                            }else{
//                                if(y > 0){
//                                    if(x > 0){
//                                        lastPos = QPoint(QPointF(cursorPressPos).x(), QPointF(cursorPressPos).x());
//                                    }else{
//                                        lastPos = QPoint(-QPointF(cursorPressPos).x(), QPointF(cursorPressPos).x());
//                                    }
//                                }else{
//                                    if(x > 0){
//                                        lastPos = QPoint(QPointF(cursorPressPos).x(), -QPointF(cursorPressPos).x());
//                                    }else{
//                                        lastPos = QPoint(-QPointF(cursorPressPos).x(), -QPointF(cursorPressPos).x());
//                                    }
//                                }
//                            }
//                        }
                    }
//                    lastPos = mapCursorPressPos;
                    makePath();
                }
                showChange();
            }else{
                resizeType = 0;
                this->cursorItem = nullptr;
                setFocus();
            }
        }else{
            this->cursorItem = cursorItem;
            resizeType = changeItem.indexOf(cursorItem) + 1;
        }
    }
    explicit YGraphicsArrowItem(const QPointF &pos, const QSize&, bool shiftKeyPressed): QGraphicsPolygonItem(){
        isShiftKeyPressed = shiftKeyPressed;
        itemType = YImageDrawer::Arrow;
        setPos(pos);
        rerect(startPos);
        setAcceptHoverEvents(true);
        points.resize(6);
        points[0] = QPoint(0, 0);
        setFlag(QGraphicsItem::ItemIsFocusable);
        // add by liq 13
        setFlag(QGraphicsItem::ItemIsSelectable);
    }
    virtual void focusInEvent(QFocusEvent *){
        showChange();
        // add by liq 13
        setSelected(true);
        isShiftKeyPressed = false;
    }
    virtual void focusOutEvent(QFocusEvent *){
        if(!inChangeHover()){
            hideChange();
            // add by liq 13
            setSelected(false);
        }
    }
    virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *){
        inChangeArea = true;
        scene()->setProperty("inChangeArea", inChangeArea);
        setCursor(Qt::SizeAllCursor);
    }
    virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *){
        inChangeArea = false;
        scene()->setProperty("inChangeArea", inChangeArea);
        unsetCursor();
    }
    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event){
        pressPos = event->pos();
        hideChange();
    }
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event){
        if(inChangeArea){
            if(resizeType == 0){
                QPointF pos = this->pos() - pressPos + event->pos();
                lastPos =(QPointF(lastPos) - pressPos + event->pos()).toPoint();
                setPos(pos);
                makePath();
            }
        }
    }
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *){if(inChangeArea){showChange();}}
    // add by liq 13 start
    virtual void keyPressEvent(QKeyEvent *event){
        int left = 0, top = 0, right = 0, bottom = 0;
        if(event->key() == Qt::Key_Left){
            left = -1;
        }else if(event->key() == Qt::Key_Right){
            right = 1;
        }else if(event->key() == Qt::Key_Up){
            top = -1;
        }else if(event->key() == Qt::Key_Down){
            bottom = 1;
        }else if(event->key() == Qt::Key_Delete){
               // 此处接收到的事件无法传给scene，也无法通过signals传递，因为item不是QObject，通过scene的eventFilter过滤
//            event->ignore();
//            return;
        }else if(event->key() == Qt::Key_Shift){
            isShiftKeyPressed = true;
            return;
        }
        QPointF newPos(this->pos().x() + left + right, this->pos().y() + top + bottom);
        lastPos = QPoint(QPointF(lastPos).x() + left + right, QPointF(lastPos).y() + top + bottom);
        setPos(newPos);
        makePath();
        showChange();
        QGraphicsItem::keyPressEvent(event);
    }
    virtual void keyReleaseEvent(QKeyEvent *event){
        if(event->key() == Qt::Key_Shift){
            isShiftKeyPressed = false;
        }
        QGraphicsItem::keyReleaseEvent(event);
    }
    // add by liq 13 end
    bool isShiftKeyPressed = false;
};
class YGraphicsPenItem : public QGraphicsPathItem, public YGraphicsItem
{
public:
    virtual void rerect(const QPoint& pos){
        if(lastPos == pos) return;
        lastPos = pos;
        points.append(pos - startPos);
        makePath();
    }
    char AlignPadding_YGraphicsArrowItem[7];
    QList<QPoint> points;
    void makePath(){
        QPainterPath path;
        path.moveTo(0, 0);
        for(const QPoint& p : points){
            path.lineTo(p);
        }
        setPath(path);
    }
    explicit YGraphicsPenItem(const QPointF &pos, const QSize&): QGraphicsPathItem(){
        itemType = YImageDrawer::Pen;
        setPos(pos);
        setAcceptHoverEvents(true);
        setFlag(QGraphicsItem::ItemIsFocusable);
        // add by liq 13
        setFlag(QGraphicsItem::ItemIsSelectable);
    }
    // add by liq 13 start
    virtual void focusInEvent(QFocusEvent *){
//        showChange();
        // add by liq 13
        setSelected(true);
    }
    virtual void focusOutEvent(QFocusEvent *){
        if(!inChangeHover()){
//            hideChange();
            // add by liq 13
            setSelected(false);
        }
    }
    // add by liq 13 end
    virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *){
        inChangeArea = true;
        scene()->setProperty("inChangeArea", inChangeArea);
        setCursor(Qt::SizeAllCursor);
    }
    virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *){
        inChangeArea = false;
        scene()->setProperty("inChangeArea", inChangeArea);
        unsetCursor();
    }
    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event){
        pressPos = event->pos();
        hideChange();
    }
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event){
        if(inChangeArea){
            if(resizeType == 0){
                QPointF pos = this->pos() - pressPos + event->pos();
                setPos(pos);
            }
        }
    }
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *){if(inChangeArea){showChange();}}
    // add by liq 13 start
    virtual void keyPressEvent(QKeyEvent *event){
        int left = 0, top = 0, right = 0, bottom = 0;
        if(event->key() == Qt::Key_Left){
            left = -1;
        }else if(event->key() == Qt::Key_Right){
            right = 1;
        }else if(event->key() == Qt::Key_Up){
            top = -1;
        }else if(event->key() == Qt::Key_Down){
            bottom = 1;
        }else if(event->key() == Qt::Key_Delete){
               // 此处接收到的事件无法传给scene，也无法通过signals传递，因为item不是QObject，通过scene的eventFilter过滤
//            event->ignore();
//            return;
        }
        QPointF newPos(this->pos().x() + left + right, this->pos().y() + top + bottom);
        setPos(newPos);
//        showChange();
        QGraphicsItem::keyPressEvent(event);
    }
    // add by liq 13 end
};
// liqtest0617 无影响
class YGraphicsMosaicItem : public QGraphicsItem, public YGraphicsItem
{
public:
    explicit YGraphicsMosaicItem(QImage image):
            QGraphicsItem(), basicImage(image){
        itemType = YImageDrawer::Mosaic;
//        mosaicImage = basicImage.copy();

        // liqtest0617 无影响
        // del by liq 13
//        map.resize(image.width());
//        for(QVector<bool>& maps : map){
//            maps.resize(image.height());
//            for(bool& b : maps){
//                b = false;
//            }
//        }
    }
    void setVague(int value){
        vague = int(0.3 * value);
        // modify by liq 13
//        if(vague < 3) vague = 3;
        if(vague < 1) vague = 1;
//        makeMosaic();
//        update();
    }
    inline void setThickness(int value) { thickness = value; }
    // del by liq 13
//    virtual void rerect(const QPoint& pos){
//        if(lastPos == pos) return;
//        lastPos = pos;
//        int radius = (thickness == 1 ? 9 : (thickness == 2 ? 19 : 29));
//        QRect rect(pos.x() - radius, pos.y() - radius, radius, radius);
//        if(rect.x() < 0) rect.setX(0);
//        if(rect.y() < 0) rect.setY(0);
//        if(rect.right() > basicImage.width()) rect.setRight(basicImage.width());
//        if(rect.bottom() > basicImage.height()) rect.setBottom(basicImage.height());
//        bool changed = false;
//        for(int row = rect.x(); row < rect.right(); ++row){
//            for(int col = rect.y(); col < rect.bottom(); ++col){
//                if(!map[row][col]){
//                    changed = true;
//                    map[row][col] = true;
//                }
//            }
//        }
//        if(changed) update();
//    }
    // del by liq 13
//    void makeMosaic(){
//        for(int row = 0; row < basicImage.width(); ++row){
//            int rr = int(row / vague) * vague;
//            for(int col = 0; col < basicImage.height(); ++col){
//                int cc = int(col / vague) * vague;
//                mosaicImage.setPixel(row, col, basicImage.pixel(rr, cc));
//            }
//        }
//    }
    virtual QRectF boundingRect() const{ return basicImage.rect(); }
    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem* option, QWidget* widget){
//        painter->drawImage()

        // del by liq 13
//        for(int row = 0; row < map.size(); ++row){
//            for(int col = 0; col < basicImage.height(); ++col){
//                // liqtext0617 此处逻辑造成绘图时卡顿，原因未知！！！
//                if(map[row][col]){
//                    painter->setPen(mosaicImage.pixelColor(row, col));
//                    painter->drawPoint(row, col);
//                }
//            }
//        }
        QVector<QRect> rects = getRects();
        QRect areaRect = basicImage.rect();
        for(QRectF rect:rects)
        {
////            QColor lefttop = basicImage.pixel(rect.x(),rect.y());
////            QColor righttop = basicImage.pixel(rect.x()+rect.width(),rect.y());
////            QColor leftbottom = basicImage.pixel(rect.x(),rect.y()+rect.height());
////            QColor rightbottom = basicImage.pixel(rect.x()+rect.width(),rect.y()+rect.height());
////            QColor center = basicImage.pixel(rect.x()+rect.width()/2,rect.y()+rect.height()/2);

//            int x = int(rect.x() / vague) * vague;
//            int y = int(rect.y() / vague) * vague;
//            int xw = x + rect.width();
//            int yh = y + rect.height();
////            int xw = int((rect.x() + rect.width()) / vague) * vague;
////            int yh = int((rect.y() + rect.height()) / vague) * vague;
//            if(xw > basicImage.width()) xw = basicImage.width();
//            if(yh > basicImage.height()) yh = basicImage.height();

//            QColor lefttop = basicImage.pixel(x,y);
//            QColor righttop = basicImage.pixel(xw,y);
//            QColor leftbottom = basicImage.pixel(x,yh);
//            QColor rightbottom = basicImage.pixel(xw,yh);
//            QColor center = basicImage.pixel(xw/2,yh/2);

//            int r = (lefttop.red() + righttop.red() + rightbottom.red() + leftbottom.red() + center.red())/5;
//            int g = (lefttop.green() + righttop.green() + rightbottom.green() + leftbottom.green() + center.green())/5;
//            int b = (lefttop.blue() + righttop.blue() + rightbottom.blue() + leftbottom.blue() + center.blue())/5;

            int red = 0, green = 0, blue = 0;
//            int x = rect.x();
//            int y = rect.y();
            int x = int(rect.x() / vague) * vague;
            int y = int(rect.y() / vague) * vague;
            int xw = x + rect.width();
            int yh = y + rect.height();
            if(xw > areaRect.right()) xw = areaRect.right();
            if(yh > areaRect.bottom()) yh = areaRect.bottom();
//            if(xw > basicImage.width()) xw = basicImage.width();
//            if(yh > basicImage.height()) yh = basicImage.height();

            //遍历方格的点
            int pointCnt = 0;
            for (int i = x; i < xw; i++){
                for (int j = y; j < yh; j++){
                    //获取该点的颜色
                    QColor color = basicImage.pixel(i, j);
                    //提取该点颜色的红绿蓝值
                    red += color.red();
                    green += color.green();
                    blue += color.blue();
                    pointCnt++;
                }
            }
            if(pointCnt == 0){
                // 切记！！为0时以下除法会崩溃，需要跳过
                continue;
            }
            //求平均
            int r = red / pointCnt;
            int g = green / pointCnt;
            int b = blue / pointCnt;

            QBrush brush(QColor(r,g,b),Qt::SolidPattern);
            painter->fillRect(rect,brush);
//            update();
        }
    }

    // add by liq 13 start
    QVector<QRect> getRects()
    {
        QVector<QRect> rects;

        QRect areaRect = basicImage.rect();

        for(QPoint point:m_points)
        {
            // 如果超出截图区域，则不处理
            if(!areaRect.contains(point)){
                continue;
            }

            bool hasInclude = false;
            for(QRect existRect:rects)
            {
                if(existRect.contains(point) == true)
                {
                    hasInclude = true;
                    break;
                }
            }
            if(hasInclude == true){
                continue;
            }

            // add by liq 13 start
            if(lastPos == point){
                continue;
            }
            lastPos = point;
            int radius = (thickness == 1 ? 9 : (thickness == 2 ? 19 : 29));
//            QRect rect(point.x() - radius, point.y() - radius, radius, radius);
//            if(rect.x() < 0) rect.setX(0);
//            if(rect.y() < 0) rect.setY(0);
//            if(rect.right() > basicImage.width()) rect.setRight(basicImage.width());
//            if(rect.bottom() > basicImage.height()) rect.setBottom(basicImage.height());
            // add by liq 13 end

//            int rowIndex = (point.y()-areaRect.y())/thickness;
//            int colInex = (point.x()-areaRect.x())/thickness;

//            double x = areaRect.x() + colInex * thickness;
//            double y = areaRect.y() + rowIndex * thickness;

//            QRect rect(x - radius, y - radius, radius, radius);

            double x = point.x();
            double y = point.y();

            QRect rect(x - radius/2, y - radius, radius/2, radius/2);

            if(rect.x() < 0) rect.setX(0);
            if(rect.y() < 0) rect.setY(0);
            if(rect.right() > areaRect.right()) rect.setRight(areaRect.right());
            if(rect.bottom() > areaRect.bottom()) rect.setBottom(areaRect.bottom());
//            if(rect.right() > basicImage.width()) rect.setRight(basicImage.width());
//            if(rect.bottom() > basicImage.height()) rect.setBottom(basicImage.height());

//            QRect rect(x,y,vague,vague);
            rects.append(rect);

            QRect rect2(x - radius/2, rect.y() + radius/2 , radius/2, radius/2);

            if(rect2.x() < 0) rect2.setX(0);
            if(rect2.y() < 0) rect2.setY(0);
            if(rect2.right() > areaRect.right()) rect2.setRight(areaRect.right());
            if(rect2.bottom() > areaRect.bottom()) rect2.setBottom(areaRect.bottom());
//            if(rect2.right() > basicImage.width()) rect2.setRight(basicImage.width());
//            if(rect2.bottom() > basicImage.height()) rect2.setBottom(basicImage.height());

            rects.append(rect2);
        }
        return rects;
    }

    QVector<QPoint> m_points;     //点列表
    // add by liq 13 end

// modify by liq 13
//    QImage basicImage, mosaicImage;
    QImage basicImage;
//    QVector<QVector<bool> > map;
    int thickness, vague;
};
static inline int boundingWidth(QFontMetrics& fm, const QString& content){
#if (QT_VERSION >= QT_VERSION_CHECK(5,11,0))
        return fm.horizontalAdvance(content);
#else
        return fm.width(content);
#endif
}

// add by liq 13 start
YGraphicsTextItemRect::YGraphicsTextItemRect(QWidget* parent) : QFrame(parent){
    setWindowFlags(Qt::FramelessWindowHint);
    setAttribute(Qt::WA_TranslucentBackground);
    // add by liq 13
    // 添加以下属性，允许切换输入法
    setAttribute(Qt::WA_InputMethodEnabled);
}

void YGraphicsTextItemRect::paintEvent(QPaintEvent*){
    QPainter painter(this);
    QPen pen(color, 2);
    painter.setPen(pen);
    painter.drawRect(this->rect());
}

void YGraphicsTextItemRect::mousePressEvent(QMouseEvent *event){
    this->setFocus();
    this->color = Qt::green;
    update();
    emit sigPressRect();
}

//void YGraphicsTextItemRect::mouseMoveEvent(QMouseEvent *event){

//}


PlainTextEdit::PlainTextEdit(QWidget* parent) : QPlainTextEdit(parent){
    setStyleSheet(QStringLiteral("TextWidget { background: transparent; }"));
    connect(this, &PlainTextEdit::textChanged, this, &PlainTextEdit::adjustSize);
    connect(this, &PlainTextEdit::textChanged, this, &PlainTextEdit::emitTextUpdated);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setContextMenuPolicy(Qt::NoContextMenu);
};

// 重写是为了解决多屏幕中输入法候选窗显示不到正确屏幕的问题
QVariant PlainTextEdit::inputMethodQuery(Qt::InputMethodQuery query) const{
    QVariant v;
    const QPoint offset(screenShotRect);
    switch (query)
    {
    case Qt::ImHints:
        v = QWidget::inputMethodQuery(query);
        break;
    default:
        v = QPlainTextEdit::inputMethodQuery(query);
//            if (v.isValid())
//            {
//                const QPoint offset(contentsRect().topLeft());
//                const QPoint offset(1920,100);
            if (v.type() == QVariant::RectF)
                v = v.toRectF().toRect().translated(offset);
            else if (v.type() == QVariant::PointF)
                v = v.toPointF().toPoint() + offset;
            else if (v.type() == QVariant::Rect)
                v = v.toRect().translated(offset);
            else if (v.type() == QVariant::Point)
                v = v.toPoint() + offset;
//            }
    }
    return v;
}

void PlainTextEdit::showEvent(QShowEvent* e)
{
    QFont font;
    QFontMetrics fm(font);
    setFixedWidth(fm.lineSpacing() * 6);
    setFixedHeight(fm.lineSpacing() * 2.5);
    m_baseSize = size();
    m_minSize = m_baseSize;
    QPlainTextEdit::showEvent(e);
    adjustSize();
}

void PlainTextEdit::resizeEvent(QResizeEvent* e)
{
    m_minSize.setHeight(qMin(m_baseSize.height(), height()));
    m_minSize.setWidth(qMin(m_baseSize.width(), width()));
    QPlainTextEdit::resizeEvent(e);
}

void PlainTextEdit::setFont(const QFont& f)
{
    QPlainTextEdit::setFont(f);
    adjustSize();
}

void PlainTextEdit::setTextColor(const QColor& c)
{
    QString s(
      QStringLiteral("TextWidget { background: transparent; color: %1; }"));
    setStyleSheet(s.arg(c.name()));
}

void PlainTextEdit::adjustSize()
{
    QString&& text = this->toPlainText();

    QFontMetrics fm(font());
    QRect bounds = fm.boundingRect(QRect(), 0, text);
    int pixelsWide = bounds.width() + fm.lineSpacing();
    int pixelsHigh = bounds.height() * 1.15 + fm.lineSpacing();
    if (pixelsWide < m_minSize.width()) {
        pixelsWide = m_minSize.width();
    }
    if (pixelsHigh < m_minSize.height()) {
        pixelsHigh = m_minSize.height();
    }

    this->setFixedSize(pixelsWide, pixelsHigh);
}

void PlainTextEdit::emitTextUpdated()
{
    emit textUpdated(this->toPlainText());
}

// add by liq 13 end

class YGraphicsTextItem : public QGraphicsProxyWidget, public YGraphicsItem
{
public:
    // modify by liq 13
//    void resize(const QString& content = "占位"){
//        QFontMetrics fm(edit->font());
//        int width = boundingWidth(fm, "占位"), height = 4;
//        for(const QString& line : content.split('\n')){
//            int tw = boundingWidth(fm, line + "占");
//            if(tw > width)width = tw;
//            height += fm.lineSpacing();
//        }

//        QGraphicsWidget::resize(width, height);
//        edit->resize(width, height);
//        setMinimumHeight(height);
//        setMaximumHeight(height);
//        update();
//    }

//    void resize(const QString& content = "占位"){
//        QFontMetrics fm(edit->font());
//        int width = boundingWidth(fm, "占位");
//        int height = 4;
//        for(const QString& line : content.split('\n')){
//            int tw = boundingWidth(fm, line + "占");
//            if(tw > width){
//                width = tw;
//            }
//        }
//        width = width + 5;

//        int lineCount = edit->document()->lineCount()+1;
//        int lineSpacing = fm.lineSpacing();

//        int testHeight = lineCount * lineSpacing;
//        if(testHeight > height){
//            height = testHeight;
//        }
//        QGraphicsWidget::resize(width+60, height+20);
//        textRect->resize(width+60, height+20);
//        edit->setGeometry(10, 10, width+60, height+10);
//        edit->show();
//        edit->setFixedHeight(height+10);
//        edit->setFixedWidth(width+60);
//        update();
//    }

    void resize(const QString& content = ""){
        int fixHeight = edit->height() > edit->m_minSize.height() ? edit->height() : edit->m_minSize.height();
        int fixWidth = edit->width() > edit->m_minSize.width() ? edit->width() : edit->m_minSize.width();
        QGraphicsWidget::resize(fixWidth+30, fixHeight+10);
        textRect->resize(fixWidth+30, fixHeight+10);
        edit->setGeometry(10, 5, fixWidth+30, fixHeight);
//        edit->show();
        edit->setFixedHeight(fixHeight);
        edit->setFixedWidth(fixWidth+30);
        update();
    }

    void editClearCursor(){
        QTextCursor c = edit->textCursor();
        c.clearSelection();
        edit->setTextCursor(c);
    }

    std::function<void()> func_ptr_setFontColor =  std::bind(&YGraphicsTextItem::setFontColor, this);
    void setFontColor(){
        this->edit->setStyleSheet(QString("color:rgb(%1,%2,%3);background-color:rgba(0,0,0,0);border:none;")
            .arg(currentColor.red()).arg(currentColor.green()).arg(currentColor.blue()));
    }
    std::function<void()> func_ptr_setFontSize =  std::bind(&YGraphicsTextItem::setFontSize, this);
    void setFontSize(){
//        if(this->edit->fontInfo().pointSize() == currentSize){
//            return;
//        }
        QFont newFont = this->edit->font();
        newFont.setPointSize(currentSize);
        this->edit->setFont(newFont);
        this->resize(this->edit->toPlainText());
    }
    std::function<void()> func_ptr_setFontWeight =  std::bind(&YGraphicsTextItem::setFontWeight, this);
    void setFontWeight(){
//        if(this->edit->fontInfo().weight() == currentWeight){
//            return;
//        }
        QFont newFont = this->edit->font();
        newFont.setWeight(currentWeight);
        this->edit->setFont(newFont);
//        this->resize(this->edit->toPlainText());
    }

    YGraphicsTextItem(): QGraphicsProxyWidget(){
        itemType = YImageDrawer::Text;
        setAcceptHoverEvents(true);
        setFlag(QGraphicsItem::ItemIsFocusable);
        // add by liq 13
        setFlag(QGraphicsItem::ItemIsSelectable);

        // add by liq 13
        textRect = new YGraphicsTextItemRect;
        setWidget(textRect);

        // modify by liq 13
//        edit = new QPlainTextEdit;
        edit = new PlainTextEdit(textRect);
//        edit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
//        edit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
//        edit->setContextMenuPolicy(Qt::NoContextMenu);
        // del by liq 13
//        setWidget(edit);
        edit->installEventFilter(this);
//        edit->setStyleSheet(QString("color:white;background-color:rgba(0,0,0,120);border-radius:5px;border:none;"));
        // modify by liq 13
//        edit->connect(edit, &QPlainTextEdit::textChanged, [this]{resize(edit->toPlainText());});
        edit->connect(edit, &PlainTextEdit::textChanged, [this]{resize(edit->toPlainText());});
        // add by liq 13
        edit->connect(textRect, &YGraphicsTextItemRect::sigPressRect, [this]{editClearCursor();});
        edit->show();
    }

    bool eventFilter(QObject* object, QEvent* event){
        if(event->type() == QEvent::FocusIn){
            scene()->setProperty("OccupyFocus", true);
        }else if(event->type() == QEvent::FocusOut){
            scene()->setProperty("OccupyFocus", false);
            if(edit->toPlainText().isEmpty() && !activeWindowFocus){
                // del by liq 13
                // 无输入时直接点击外框，会崩溃，此代码目的应该是删除为空的框，return true也会崩溃，暂且注掉
//                emit edit->customContextMenuRequested(QPoint());
            }else{
                update();
            }
        }
//        else if(event->type() == QEvent::InputMethodQuery){
//            QInputMethodEvent *input = static_cast<QInputMethodEvent *>(event);
//            QInputMethodQueryEvent *inputq = static_cast<QInputMethodQueryEvent *>(event);
//            QWidget *fw = QWidget::keyboardGrabber();
//            fw->inputMethodQuery(Qt::ImMicroFocus).


//        }
        return QObject::eventFilter(object, event);
    }
    // del by liq 13 start
//    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
//        QGraphicsProxyWidget::paint(painter, option, widget);
//        if(hasFocus() || edit->hasFocus() || activeWindowFocus){
//            painter->setPen(QPen(Qt::red, 2));
//            painter->drawRect(rect());
//        }
//    }
    // del by liq 13 end

    // add by liq 13 start
    virtual void focusInEvent(QFocusEvent *e){
//        showChange();
        // add by liq 13
        setSelected(true);
        // 强制重绘textRect
        textRect->color = Qt::red;
        textRect->update();
//        edit->setFocusPolicy(Qt::ClickFocus);
//        edit->setReadOnly(false);
//        QTextDocument* document = edit->document();
//        QTextCursor cursor;
//        cursor = document->find("FIELD",QTextDocument::FindCaseSensitively);
//        int pos = cursor.position();
//        QTextCursor cs = edit->textCursor();
//        cs.movePosition(QTextCursor::Start);
//        cs.movePosition(QTextCursor::NextCharacter,QTextCursor::MoveAnchor,pos);
//        edit->setTextCursor(cs);
//        edit->ensureCursorVisible();
//        edit->setFocus();
//        edit->setCursorWidth(15);
        QGraphicsProxyWidget::focusInEvent(e);
    }
    virtual void focusOutEvent(QFocusEvent *e){
        if(!inChangeHover()){
//            hideChange();
            // add by liq 13
            setSelected(false);
            editClearCursor();
        }
        // 强制重绘textRect
        textRect->color = Qt::transparent;
        textRect->update();
        // 使光标不显示
//        edit->setReadOnly(true);
//        edit->clearFocus();
        QGraphicsProxyWidget::focusOutEvent(e);
    }
    // add by liq 13 end

    virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event){
        QPointF epos = event->pos();
        bool xValid = ((epos.x() >= rect().x() && epos.x() <= rect().x() + 2) ||
                       (epos.x() <= rect().right() && epos.x() >= rect().right() - 2));
        bool yValid = ((epos.y() >= rect().y() && epos.y() <= rect().y() + 2) ||
                       (epos.y() <= rect().bottom() && epos.y() >= rect().bottom() - 2));
        inChangeArea = (xValid || yValid);
        scene()->setProperty("inChangeArea", true);
        if(inChangeArea){
            setCursor(Qt::SizeAllCursor);
            // add by liq 13
            if(!edit->hasFocus() && textRect->color != Qt::green){
                textRect->color = Qt::lightGray;
                textRect->update();
            }
        }else{
            setCursor(Qt::IBeamCursor);
        }
    }
    virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *){
        inChangeArea = false;
        scene()->setProperty("inChangeArea", false);
        unsetCursor();
        // add by liq 13
        if(!edit->hasFocus() && textRect->color != Qt::green){
            textRect->color = Qt::transparent;
            textRect->update();
        }
    }
    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event){
        pressPos = event->pos();
        // add by liq 13
        if(textRect->color != Qt::red){
            textRect->color = Qt::red;
            textRect->update();
        }
        QGraphicsProxyWidget::mousePressEvent(event);
    }
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event){
        if(inChangeArea){
            if(resizeType == 0){
                QPointF pos = this->pos() - pressPos + event->pos();
                setPos(pos);
            }
        }
        QGraphicsProxyWidget::mouseMoveEvent(event);
    }
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent){
        if(!inChangeArea){
            edit->setFocus();
            if(edit->textCursor().selectedText() == ""){
                edit->setTextCursor(edit->cursorForPosition(mouseEvent->pos().toPoint()-QPoint(10,5)));
            }
        }
        QGraphicsProxyWidget::mouseReleaseEvent(mouseEvent);
    }

    // add by liq 13 start
    virtual void keyPressEvent(QKeyEvent *event){
        if(textRect->hasFocus()){
            int left = 0, top = 0, right = 0, bottom = 0;
            if(event->key() == Qt::Key_Left){
                left = -1;
            }else if(event->key() == Qt::Key_Right){
                right = 1;
            }else if(event->key() == Qt::Key_Up){
                top = -1;
            }else if(event->key() == Qt::Key_Down){
                bottom = 1;
            }
            QPointF newPos(this->pos().x() + left + right, this->pos().y() + top + bottom);
            setPos(newPos);
    //        showChange();
        }
        if (event->key() == Qt::Key_B) {
            if (event->modifiers() & Qt::ControlModifier) {
//                int oldTextWeight = edit->fontInfo().weight();
//                bool oldTextIsBold = edit->fontInfo().bold();
                QFont font = edit->font();
                if(edit->fontInfo().bold()){
                    font.setWeight(QFont::Normal);
                }else{
                    font.setWeight(QFont::Bold);
                }
                edit->setFont(font);
//                currentWeight =  edit->fontInfo().weight();
//                currentFontIsBold = edit->fontInfo().bold();

//                // undo/redo
//                std::function<void()> m_func_ptr_setFontWeight = this->func_ptr_setFontWeight;
//                QUndoCommand *changeTextItemWeightCommand = new ChangeTextItemWeightCommand(this, oldTextWeight, oldTextIsBold, m_func_ptr_setFontWeight);
//                // push时方法会先执行一次，所以此undo/redo逻辑放在change之前
//                m_undoStack->push(changeTextItemWeightCommand);
            }
        }
      QGraphicsProxyWidget::keyPressEvent(event);
    }
    // add by liq 13 end
public:
    char AlignPadding_YGraphicsArrowItem[7];
    // modify by liq 13
//    QPlainTextEdit* edit;
    PlainTextEdit* edit;
    // add by liq 13
    YGraphicsTextItemRect* textRect;
};
//class YGraphicsTipItemPanel : public QFrame
//{
//public:
    YGraphicsTipItemPanel::YGraphicsTipItemPanel(QWidget* parent) : QFrame(parent){
        setWindowFlags(Qt::FramelessWindowHint);
        setAttribute(Qt::WA_TranslucentBackground);
        // add by liq 13
        // 添加以下属性，允许切换输入法
        setAttribute(Qt::WA_InputMethodEnabled);
//        ++count;
        count++;
        self = count;
        isShow = false;
//        this->setMouseTracking(true);

//        this->installEventFilter(this);
    }
//    ~YGraphicsTipItemPanel(){
//        --count;
//    }
    void YGraphicsTipItemPanel::paintEvent(QPaintEvent*){
        QRectF rect(0, 5, 20, 20);
        QPainter painter(this);
        painter.setPen(Qt::NoPen);
        painter.setBrush(color);
        painter.drawEllipse(rect);
        painter.setBrush(QColor(0,0,0,120));
        if(isShow){
            static QPoint points[3] = {QPoint(30, 10), QPoint(30, 20), QPoint(24, 15)};
            painter.drawPolygon(points, 3);
        }
        painter.setPen((color == Qt::white ? Qt::black : Qt::white));
        painter.setBrush(Qt::NoBrush);
        painter.drawText(rect, Qt::AlignCenter, QString::number(self));
        painter.setPen(Qt::NoPen);
        painter.fillRect(this->rect(), QColor(0,0,0,0));
    }

    void YGraphicsTipItemPanel::mousePressEvent(QMouseEvent *event){
        this->setFocus();
        emit sigPressPanel();
    }

//    void YGraphicsTipItemPanel::mouseMoveEvent(QMouseEvent *event){

//    }

//    QColor color = Qt::red;
//    static int count;
//    int self;
//};
int YGraphicsTipItemPanel::count = 0;

class YGraphicsTipItem : public QGraphicsProxyWidget, public YGraphicsItem
{
public:
    // modify by liq 13
//    void resize(const QString& content = "占位"){
//        QFontMetrics fm(edit->font());
//        int width = boundingWidth(fm, "占位"), height = 4;
//        for(const QString& line : content.split('\n')){
//            int tw = boundingWidth(fm, line + "占");
//            if(tw > width) width = tw;
//            height += fm.lineSpacing();
//        }

//        QGraphicsWidget::resize(width + 30, height);
//        panel->resize(width + 30, height);
//        edit->setGeometry(30, 0, width, height);
//        edit->show();
//        setMinimumHeight(height);
//        setMaximumHeight(height);
//        update();
//    }

//    void resize(const QString& content = "占位"){
//        QFontMetrics fm(edit->font());
//        int width = boundingWidth(fm, "占位");
//        int height = 4;
//        for(const QString& line : content.split('\n')){
//            int tw = boundingWidth(fm, line + "占");
//            if(tw > width){
//                width = tw;
//            }
//        }
//        width = width + 5;

//        int lineCount = edit->document()->lineCount()+1;
//        int lineSpacing = fm.lineSpacing();

//        int testHeight = lineCount * lineSpacing;
//        if(testHeight > height){
//            height = testHeight;
//        }
//        QGraphicsWidget::resize(width + 60, height);
//        panel->resize(width + 30, height);
//        edit->setGeometry(30, 0, width, height);
//        edit->show();
//        edit->setFixedHeight(height);
//        edit->setFixedWidth(width + 30);
//        update();
//    }

    void resize(const QString& content = ""){
        int fixHeight = edit->height() > edit->m_minSize.height() ? edit->height() : edit->m_minSize.height();
        int fixWidth = edit->width() > edit->m_minSize.width() ? edit->width() : edit->m_minSize.width();
        QGraphicsWidget::resize(fixWidth + 60, fixHeight);
        panel->resize(fixWidth + 30, fixHeight);
        edit->setGeometry(30, 0, fixWidth, fixHeight);
//        edit->show();
        edit->setFixedHeight(fixHeight);
        edit->setFixedWidth(fixWidth + 30);
        update();
    }

    void editClearCursor(){
        QTextCursor c = edit->textCursor();
        c.clearSelection();
        edit->setTextCursor(c);
    }

    std::function<void()> func_ptr_setFontSize =  std::bind(&YGraphicsTipItem::setFontSize, this);
    void setFontSize(){
//        if(this->edit->fontInfo().pointSize() == currentSize){
//            return;
//        }
        QFont newFont = this->edit->font();
        newFont.setPointSize(currentSize);
        this->edit->setFont(newFont);
        this->resize(this->edit->toPlainText());
    }
    std::function<void()> func_ptr_setFontWeight =  std::bind(&YGraphicsTipItem::setFontWeight, this);
    void setFontWeight(){
//        if(this->edit->fontInfo().weight() == currentWeight){
//            return;
//        }
        QFont newFont = this->edit->font();
        newFont.setWeight(currentWeight);
        this->edit->setFont(newFont);
//        this->resize(this->edit->toPlainText());
    }

    YGraphicsTipItem(): QGraphicsProxyWidget(){
        itemType = YImageDrawer::Tip;
        setAcceptHoverEvents(true);
        setFlag(QGraphicsItem::ItemIsFocusable);
        // add by liq 13
        setFlag(QGraphicsItem::ItemIsSelectable);

        panel = new YGraphicsTipItemPanel;
        panel->isShow = true;
        setWidget(panel);

        // modify by liq
//        edit = new QPlainTextEdit(panel);
        edit = new PlainTextEdit(panel);
//        edit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
//        edit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
//        edit->setContextMenuPolicy(Qt::NoContextMenu);
        edit->installEventFilter(this);
        edit->setStyleSheet(QString("color:white;background-color:rgba(0,0,0,120);border-radius:5px;border:none;"));
        // mofiby by liq 13
//        edit->connect(edit, &QPlainTextEdit::textChanged, [this]{resize(edit->toPlainText());});
        edit->connect(edit, &PlainTextEdit::textChanged, [this]{resize(edit->toPlainText());});
        // add by liq 13
        edit->connect(panel, &YGraphicsTipItemPanel::sigPressPanel, [this]{editClearCursor();});
        edit->show();
    }

    bool eventFilter(QObject* object, QEvent* event){
        if(event->type() == QEvent::FocusIn){
            scene()->setProperty("OccupyFocus", true);
        }else if(event->type() == QEvent::FocusOut){
            scene()->setProperty("OccupyFocus", false);
            if(edit->toPlainText().isEmpty() && !activeWindowFocus){
                // 无输入时直接点击外框，虽然未发现崩溃，但应该不需要删除为空的，暂且注掉
//                emit edit->customContextMenuRequested(QPoint());
            }else{
                update();
            }
        }
        return QObject::eventFilter(object, event);
    }

    // add by liq 13 start
    virtual void focusInEvent(QFocusEvent *e){
//        showChange();
        // add by liq 13
        setSelected(true);
        if(edit->isHidden()){
            panel->isShow = true;
            edit->show();
        }
        QGraphicsProxyWidget::focusInEvent(e);
    }
    virtual void focusOutEvent(QFocusEvent *e){
        if(!inChangeHover()){
//            hideChange();
            // add by liq 13
            setSelected(false);
            editClearCursor();
            if(edit->toPlainText() == ""){
                panel->isShow = false;
                edit->hide();
            }
        }
        QGraphicsProxyWidget::focusOutEvent(e);
    }
    // add by liq 13 end

    virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event){
        QPointF epos = event->pos();
        inChangeArea = (epos.x() < 20 && epos.y() < 20);
        scene()->setProperty("inChangeArea", true);
        if(inChangeArea){
            setCursor(Qt::SizeAllCursor);
        }else{
            setCursor(Qt::IBeamCursor);
        }
    }
    virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *){
        inChangeArea = false;
        scene()->setProperty("inChangeArea", false);
        unsetCursor();
    }
    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event){
        pressPos = event->pos();
        QGraphicsProxyWidget::mousePressEvent(event);
    }
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event){
        if(inChangeArea){
            if(resizeType == 0){
                QPointF pos = this->pos() - pressPos + event->pos();
                setPos(pos);
            }
        }
        QGraphicsProxyWidget::mouseMoveEvent(event);
    }
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent){
        if(!inChangeArea){
            edit->setFocus();
            if(edit->textCursor().selectedText() == ""){
                edit->setTextCursor(edit->cursorForPosition(mouseEvent->pos().toPoint()-QPoint(30,0)));
            }
        }
        QGraphicsProxyWidget::mouseReleaseEvent(mouseEvent);
    }
    // add by liq 13 start
    virtual void keyPressEvent(QKeyEvent *event){
        if(panel->hasFocus()){
            int left = 0, top = 0, right = 0, bottom = 0;
            if(event->key() == Qt::Key_Left){
                left = -1;
            }else if(event->key() == Qt::Key_Right){
                right = 1;
            }else if(event->key() == Qt::Key_Up){
                top = -1;
            }else if(event->key() == Qt::Key_Down){
                bottom = 1;
            }else if(event->key() == Qt::Key_Delete){
                   // 此处接收到的事件无法传给scene，也无法通过signals传递，因为item不是QObject，通过scene的eventFilter过滤
    //            event->ignore();
    //            return;
            }
            QPointF newPos(this->pos().x() + left + right, this->pos().y() + top + bottom);
            setPos(newPos);
    //        showChange();
        }
        if (event->key() == Qt::Key_B) {
            if (event->modifiers() & Qt::ControlModifier) {
                QFont font = edit->font();
                if(edit->fontInfo().bold()){
                    font.setWeight(QFont::Normal);
                }else{
                    font.setWeight(QFont::Bold);
                }
                edit->setFont(font);
            }
        }
        QGraphicsProxyWidget::keyPressEvent(event);
    }
    // add by liq 13 end
public:
    char AlignPadding_YGraphicsArrowItem[7];
    // modify by liq 13
//    QPlainTextEdit* edit;
    PlainTextEdit* edit;
    YGraphicsTipItemPanel* panel;
};
};
using namespace Y_Image_Drawer_GUI;

QCursor getMosaicCursor(int thickness){
    static QCursor min = QCursor(QPixmap(":/min.png"), 9, 9);
    static QCursor middle = QCursor(QPixmap(":/middle.png"), 19, 19);
    static QCursor max = QCursor(QPixmap(":/max.png"), 29, 29);
    return (thickness == 1 ? min : (thickness == 2 ? middle : max));
}

YImageDrawer::YImageDrawer(const QImage& image, QRect& selectedRect, QWidget *parent) : QWidget(parent), image(image)
{
//    setFixedSize(image.size());
    setFixedSize(selectedRect.size());
//    scene = new QGraphicsScene(image.rect(), this);
    scene = new DiagramScene(image.rect(), this);
//    scene->setItemIndexMethod(QGraphicsScene::NoIndex);
    view = new QGraphicsView(scene, this);
    view->setStyleSheet("border: none;");

    view->setRenderHint(QPainter::Antialiasing);
    // add by liq 15
    // 用来在对图片进行缩放时启用线性插值算法而不是最邻近算法
    view->setRenderHint(QPainter::SmoothPixmapTransform);

    view->viewport()->installEventFilter(this);
    // 拦截item上的事件
    scene->installEventFilter(this);
//    view->resize(image.size());
    view->resize(selectedRect.size());

    //add by liq 12
    view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    pm = scene->addPixmap(QPixmap::fromImage(image));
//    this->pm->setPos(QPoint(selectedRect.x(), selectedRect.y()));
    scene->setProperty("inChangeArea", false);
    scene->setSceneRect(view->rect());

    connect(scene, &QGraphicsScene::focusItemChanged,
            [this](QGraphicsItem *newFocus, QGraphicsItem *oldFocus, Qt::FocusReason reason){
        if(oldFocus && reason == Qt::ActiveWindowFocusReason){
            if(scene->focusItem()){
                focusItem = dynamic_cast<YGraphicsItem*>(scene->focusItem());
                focusItem->activeWindowFocus = true;
            }
        }else if(focusItem){
            focusItem->activeWindowFocus = false;
            focusItem = nullptr;
        }
        if(newFocus && reason == Qt::MouseFocusReason){
            UpdateToolSetting();
        }
    });
    connect(scene, &DiagramScene::sigItemMoved, this, &YImageDrawer::onItemMoved);
//    connect(scene, &DiagramScene::sigItemSizeChanged, this, &YImageDrawer::onItemSizeChanged);
    connect(scene, &DiagramScene::sigDoUndoAction, this, &YImageDrawer::onDoUndoAction);
    connect(scene, &DiagramScene::sigDoRedoAction, this, &YImageDrawer::onDoRedoAction);

    screenShotRect = selectedRect.topLeft();
// liqtest0617 无影响
    // modify by liq 13 移至局部控制
//    mosaic = new YGraphicsMosaicItem(image);
//    scene->addItem(mosaic);
//    items.append(mosaic);

    m_undoStack = new QUndoStack(this);
    connect(m_undoStack, SIGNAL(canUndoChanged(bool)), this, SIGNAL(sigUpdateUndoBtnState(bool)));
    connect(m_undoStack, SIGNAL(canRedoChanged(bool)), this, SIGNAL(sigUpdateRedoBtnState(bool)));

//    m_undoView = new QUndoView(m_undoStack);
//    m_undoView->setWindowTitle(tr("Command List"));
//    m_undoView->show();
//    m_undoView->setAttribute(Qt::WA_QuitOnClose, false);
}

// add by liq 12
void YImageDrawer::saveScreenShot(){
    emit sigSaveScreenShot();
}
void YImageDrawer::download(){
    emit sigDownload();
}
void YImageDrawer::stickerDesktop(){
    emit sigStickerDesktop();
}
void YImageDrawer::quitScreenshot(){
    emit sigScreenshotCancel();
    emit sigQuitScreenshot();
}

// add by liq 12
void YImageDrawer::contextMenuEvent(QContextMenuEvent *) {
    emit sigGetPinKey();

    menu_ = new QMenu(this);
    menu_->addAction(QStringLiteral("完成"), this, SLOT(saveScreenShot()), QKeySequence("Ctrl+C"));
    menu_->addAction(QStringLiteral("保存"), this, SLOT(download()), QKeySequence("Ctrl+S"));
    // 单个快捷键不起作用，比如F6
//    menu_->addAction(QStringLiteral("钉在桌面"), this, SLOT(stickerDesktop()), QKeySequence(PIN_KEY));
    menu_->addAction(QStringLiteral("钉在桌面"), this, SLOT(stickerDesktop()), QKeySequence("Ctrl+" + PIN_KEY));
    // 撤销的快捷键不好用
//    menu_->addAction(QStringLiteral("撤销"), this, SLOT(redo()), QKeySequence("Ctrl+Z"));
    QAction* undoAction = new QAction(QStringLiteral("撤销"), menu_);
    undoAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Z));
    menu_->addAction(undoAction);
    connect(undoAction, SIGNAL(triggered()), this, SLOT(undo()));
    undoAction->setEnabled(m_undoStack->canUndo());
//    menu_->addAction(QStringLiteral("重做"), this, SLOT(redo()), QKeySequence("Ctrl+Y"));
    QAction* redoAction = new QAction(QStringLiteral("重做"), menu_);
    redoAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Y));
    menu_->addAction(redoAction);
    connect(redoAction, SIGNAL(triggered()), this, SLOT(redo()));
    redoAction->setEnabled(m_undoStack->canRedo());
    menu_->addAction(QStringLiteral("退出"), this, SLOT(quitScreenshot()), QKeySequence("Esc"));
    // 右键菜单
    menu_->exec(cursor().pos());
}

void YImageDrawer::updateYImageDrawer(const QImage& image, const QRect &rect, QWidget *parent){
//            QMessageBox mb(this);
//            QString width_str = QString::number(this->size().width(), 10);
//            QString height_str = QString::number(this->size().height(), 10);
//            char* width_char;
//            char* height_char;
//            QByteArray width_qba = width_str.toLatin1();
//            QByteArray height_qba = height_str.toLatin1();
//            width_char = width_qba.data();
//            height_char = height_qba.data();
//            //设置文本框的大小
//            mb.setStyleSheet("QLabel{"
//                              "min-width: 300px;"
//                              "min-height: 150px; "
//                              "font-size:12px;"
//                              "}");
//            mb.setText(QString::fromLocal8Bit(width_char) + "|" + QString::fromLocal8Bit(height_char));
//            mb.setWindowTitle(QString::fromLocal8Bit("提示"));
//            mb.move(500,300);
//            mb.exec();

//    setFixedSize(image.size());
    // 更新图片用于马赛克
    this->image = image;
    setFixedSize(rect.size());
//    this->view->resize(image.size());
    this->view->resize(rect.size());
    this->pm->setPixmap(QPixmap::fromImage(image));
    this->scene->setSceneRect(view->rect());
//    this->pm->setPos(QPoint(rect.x(), rect.y()));

//    this->scene->removeItem(mosaic);
//    mosaic = new YGraphicsMosaicItem(image);
//    this->scene->addItem(mosaic);
    this->scene->update();

    screenShotRect = rect.topLeft();
}

void YImageDrawer::changeItemPos(const QPoint& point)
{
//    QMessageBox mb(this);
//    QString width_str = QString::number(this->size().width(), 10);
//    QString height_str = QString::number(this->size().height(), 10);
//    char* width_char;
//    char* height_char;
//    QByteArray width_qba = width_str.toLatin1();
//    QByteArray height_qba = height_str.toLatin1();
//    width_char = width_qba.data();
//    height_char = height_qba.data();
//    //设置文本框的大小
//    mb.setStyleSheet("QLabel{"
//                      "min-width: 300px;"
//                      "min-height: 150px; "
//                      "font-size:12px;"
//                      "}");
//    mb.setText(QString::fromLocal8Bit(width_char) + "|" + QString::fromLocal8Bit(height_char));
//    mb.setWindowTitle(QString::fromLocal8Bit("提示"));
//    mb.move(500,300);
//    mb.exec();

    // 马赛克单独处理
// liqtest0617
//    mosaic->setPos(mosaic->pos() + point);
    //其它图形处理
//    if(items.isEmpty()) return;
//    for(int i = 0; i < items.size(); ++i){
//        QGraphicsItem* item = items[i];
//        QPointF newPos = item->pos() + point;
//        item->setPos(newPos);
//        // 箭头单独添加此处理(重置lastPos)
//        YGraphicsItem* itm = dynamic_cast<YGraphicsItem*>(item);
//        if(itm->itemType == Arrow){
//            YGraphicsArrowItem* it = dynamic_cast<YGraphicsArrowItem*>(item);
//            it->lastPos = it->lastPos + point;
//            it->makePath();
//        }
//    }
    const QList<QGraphicsItem*> sceneItems = scene->items(Qt::AscendingOrder);
    foreach(QGraphicsItem* item, sceneItems){
        // 箭头单独添加此处理(重置lastPos)
        YGraphicsItem* itm = dynamic_cast<YGraphicsItem*>(item);
        if(itm != nullptr){
            QPointF newPos = item->pos() + point;
            item->setPos(newPos);
            if(itm->itemType == Arrow){
                YGraphicsArrowItem* it = dynamic_cast<YGraphicsArrowItem*>(item);
                it->lastPos = it->lastPos + point;
                it->makePath();
            }
        }
    }
}

void YImageDrawer::setType(int t)
{
    type = Type(t);
    if(type == Mosaic){
        // modify by liq 12
        // 不能直接在view上设置，否则会显示混乱
//        view->setCursor(getMosaicCursor(tools->getThickness()));
// liqtest0617 无影响
        view->viewport()->setCursor(getMosaicCursor(tools->getThickness()));
    }else if(type == Rect || type == Ellipse || type == Arrow || type == Pen || type == Text || type == Tip){
        view->viewport()->setCursor(QCursor(Qt::CrossCursor));
    }else{
        setViewCursor(Yuan::CustomCursor());
    }
}

void YImageDrawer::setViewCursor(const QCursor &cursor)
{
    static QCursor staticCursor = cursor;
    // modify by liq 12
    // 不能直接在view上设置，否则会显示混乱
//    view->setCursor(staticCursor);
    view->viewport()->setCursor(staticCursor);
}

void YImageDrawer::setTools(DrawTools *t)
{
    tools = t;
// liqtest0617 无影响
    // modify by liq 13 移至局部控制
//    mosaic->setThickness(tools->getThickness());
//    mosaic->setVague(tools->getVague());
}

void YImageDrawer::thicknessChanged(int thickness)
{
    if(!scene->focusItem()) return;
    QAbstractGraphicsShapeItem* item = dynamic_cast<QAbstractGraphicsShapeItem*>(scene->focusItem());
    if(item){
        YGraphicsItem* itm = dynamic_cast<YGraphicsItem*>(item);
        if(itm){
            int oldThickness = itm->currentThickness;
            QPen pen = item->pen();
            itm->currentThickness = itm->itemType == Arrow ? thickness : thickness * 2;
            pen.setWidth(itm->itemType == Arrow ? thickness : thickness * 2);
            item->setPen(pen);
            std::function<void()> m_func_ptr_makePath = nullptr;
            std::function<void()> m_func_ptr_reChangePos = nullptr;
            if(itm->itemType == Arrow){
                YGraphicsArrowItem* tipItem = dynamic_cast<YGraphicsArrowItem*>(scene->focusItem());
                if(tipItem != nullptr){
                    tipItem->makePath();
                    m_func_ptr_makePath = tipItem->fun_ptr_makePath;
                }
            }else if(itm->itemType == Rect){
                YGraphicsRectItem* rectItem = dynamic_cast<YGraphicsRectItem*>(scene->focusItem());
                if(rectItem != nullptr){
                    m_func_ptr_reChangePos = rectItem->fun_ptr_reChangePos;
                }
            }else if(itm->itemType == Ellipse){
                YGraphicsEllipseItem* ellipseItem = dynamic_cast<YGraphicsEllipseItem*>(scene->focusItem());
                if(ellipseItem != nullptr){
                    m_func_ptr_reChangePos = ellipseItem->fun_ptr_reChangePos;
                }
            }
            item->update();

            // undo/redo
            QUndoCommand *changeItemThicknessCommand = new ChangeItemThicknessCommand(scene->focusItem(), oldThickness, m_func_ptr_reChangePos, m_func_ptr_makePath);
            m_undoStack->push(changeItemThicknessCommand);
        }
    }
// liqtest0617 无影响
    // modify by liq 13 移至局部控制
//    mosaic->setThickness(thickness);
    if(type == Mosaic){
        // modify by liq 12
        // 不能直接在view上设置，否则会显示混乱
//        view->setCursor(getMosaicCursor(thickness));
        view->viewport()->setCursor(getMosaicCursor(thickness));
    }
}

void YImageDrawer::colorChanged(QColor color)
{
    if(!scene->focusItem()) return;
    YGraphicsItem* yitem = dynamic_cast<YGraphicsItem*>(scene->focusItem());
    if(scene->focusItem()->isWidget()){
        // modify by liq
        // 由于tip的panel为透明，此处改变颜色会崩溃，暂且还原
//        if(yitem->itemType == Text || yitem->itemType == Tip){
        if(yitem->itemType == Text){
            YGraphicsTextItem* textItem = dynamic_cast<YGraphicsTextItem*>(yitem);
            QColor oldTextItemColor = yitem->currentColor;
            textItem->edit->setStyleSheet(QString("color:rgb(%1,%2,%3);background-color:rgba(0,0,0,0);border:none;")
                                      .arg(color.red()).arg(color.green()).arg(color.blue()));
            yitem->currentColor = color;
            scene->focusItem()->update();

            // undo/redo
            std::function<void()> m_func_ptr_setFontColor = textItem->func_ptr_setFontColor;
            QUndoCommand *changeTextItemColorCommand = new ChangeTextItemColorCommand(scene->focusItem(), oldTextItemColor, m_func_ptr_setFontColor);
            m_undoStack->push(changeTextItemColorCommand);
        }else if(yitem->itemType == Tip){
            YGraphicsTipItem* itm = dynamic_cast<YGraphicsTipItem*>(scene->focusItem());
            QColor oldTipItemColor = yitem->currentColor;
            YGraphicsTipItemPanel *oldTipItemPanel = itm->panel;
            itm->panel->color = color;
            yitem->currentColor = color;
            itm->update();

            // undo/redo
            QUndoCommand *changeItemColorCommand = new ChangeItemColorCommand(scene->focusItem(), oldTipItemColor, oldTipItemPanel);
            m_undoStack->push(changeItemColorCommand);
        }

        return;
    }
    QAbstractGraphicsShapeItem* item = dynamic_cast<QAbstractGraphicsShapeItem*>(scene->focusItem());
    if(item){
        if(yitem->itemType == Arrow){
            item->setBrush(color);
        }else{
            QPen pen = item->pen();
            pen.setColor(color);
            item->setPen(pen);
        }

        QColor oldColor = yitem->currentColor;
        yitem->currentColor = color;
        item->update();

        // undo/redo
        QUndoCommand *changeItemColorCommand = new ChangeItemColorCommand(scene->focusItem(), oldColor, nullptr);
        m_undoStack->push(changeItemColorCommand);
    }
}

void YImageDrawer::fontChanged(const QFont &font)
{
    if(!scene->focusItem()) return;
    YGraphicsItem* yitem = dynamic_cast<YGraphicsItem*>(scene->focusItem());
    if(yitem){
        QFont newFont = font;
        if(yitem->itemType == Text){
            int oldTextFontSize = yitem->currentSize;
            YGraphicsTextItem* textItem = dynamic_cast<YGraphicsTextItem*>(scene->focusItem());

            // 执行本次变更
            newFont.setWeight(textItem->edit->fontInfo().weight());
            textItem->edit->setFont(newFont);
            textItem->resize(textItem->edit->toPlainText());
            yitem->currentSize = newFont.pointSize();

            // undo/redo
            std::function<void()> m_func_ptr_setFontSize = textItem->func_ptr_setFontSize;
            QUndoCommand *changeTextItemSizeCommand = new ChangeTextItemSizeCommand(scene->focusItem(), oldTextFontSize, m_func_ptr_setFontSize);
            // push时方法会先执行一次，所以此undo/redo逻辑放在change之前
            m_undoStack->push(changeTextItemSizeCommand);

        }else if(yitem->itemType == Tip){
            int oldTipFontSize = yitem->currentSize;
            YGraphicsTipItem* tipItem = dynamic_cast<YGraphicsTipItem*>(scene->focusItem());

            // 执行本次变更
            newFont.setWeight(tipItem->edit->fontInfo().weight());
            tipItem->edit->setFont(newFont);
            tipItem->resize(tipItem->edit->toPlainText());
            yitem->currentSize = newFont.pointSize();

            // undo/redo
            std::function<void()> m_func_ptr_setFontSize = tipItem->func_ptr_setFontSize;
            QUndoCommand *changeTextItemSizeCommand = new ChangeTextItemSizeCommand(scene->focusItem(), oldTipFontSize, m_func_ptr_setFontSize);
            // push时方法会先执行一次，所以此undo/redo逻辑放在change之前
            m_undoStack->push(changeTextItemSizeCommand);
        }
    }
}

void YImageDrawer::clearCount()
{
    YGraphicsTipItemPanel::count = 0;
}

void YImageDrawer::vagueChanged(int vague)
{
// liqtest0617 无影响
    // modify by liq 13 移至局部控制
//    mosaic->setVague(vague);
}

void YImageDrawer::undo()
{
//    if(items.isEmpty()) return;
//    QGraphicsItem* qGraphicsItem = items.takeLast();
//    scene->removeItem(qGraphicsItem);
//    delete qGraphicsItem;
    if(m_undoStack->canUndo()){
        onDoUndoAction();
    }
}

void YImageDrawer::redo(){
    if(m_undoStack->canRedo()){
        onDoRedoAction();
    }
}

void YImageDrawer::createItem(const QPoint &pos, bool shiftKeyPressed)
{
    QGraphicsItem* qGraphicsItem = nullptr;
    switch(type){
    case Rect: {
        YGraphicsRectItem* item = new YGraphicsRectItem(pos, QSizeF(2, 2), shiftKeyPressed);
        qGraphicsItem = item;
        currentItem = item;
        item->setPen(QPen(tools->getColor(), tools->getThickness() * 2));
        item->currentThickness = tools->getThickness() * 2;
        item->currentColor = tools->getColor();

    };break;
    case Ellipse: {
        YGraphicsEllipseItem* item = new YGraphicsEllipseItem(pos, QSize(2, 2), shiftKeyPressed);
        qGraphicsItem = item;
        currentItem = item;
        item->setPen(QPen(tools->getColor(), tools->getThickness() * 2));
        item->currentThickness = tools->getThickness() * 2;
        item->currentColor = tools->getColor();
    };break;
    case Arrow: {
        YGraphicsArrowItem* item = new YGraphicsArrowItem(pos, QSize(2, 2), shiftKeyPressed);
        qGraphicsItem = item;
        currentItem = item;
        QPen pen = Qt::NoPen;
        pen.setWidth(tools->getThickness());
        item->setPen(pen);
        item->setBrush(tools->getColor());
        item->currentThickness = tools->getThickness();
        item->currentColor = tools->getColor();
    };break;
    case Pen: {
        YGraphicsPenItem* item = new YGraphicsPenItem(pos, QSize(2, 2));
        qGraphicsItem = item;
        currentItem = item;
        item->setPen(QPen(tools->getColor(), tools->getThickness() * 2));
        item->currentThickness = tools->getThickness() * 2;
        item->currentColor = tools->getColor();
    };break;
    case Text: {
        YGraphicsTextItem* item = new YGraphicsTextItem;
        qGraphicsItem = item;
        currentItem = item;
        item->edit->setFont(tools->getFont());
        QColor color = tools->getColor();
        item->edit->setStyleSheet(QString("color:rgb(%1,%2,%3);background-color:rgba(0,0,0,0);border:none;")
                                  .arg(color.red()).arg(color.green()).arg(color.blue()));
        item->resize();
        item->setPos(pos);
        item->edit->setFocus();
        item->currentColor = color;
        item->currentSize = item->edit->fontInfo().pointSize();
        item->currentFontIsBold = item->edit->fontInfo().bold();
        // del by liq 13
        // 此代码目应该是想删除为空的框，但会引起崩溃，暂且注掉，而且QPlainTextEdit已重写为PlainTextEdit，使用时需要注意
//        connect(item->edit, &QPlainTextEdit::customContextMenuRequested, [this, qGraphicsItem]{
//            items.removeOne(qGraphicsItem);
//            scene->removeItem(qGraphicsItem);
//            QTimer::singleShot(1000, [qGraphicsItem]{
//                if(qGraphicsItem) delete qGraphicsItem;
//            });
//        });
    };break;
    case Tip: {
        YGraphicsTipItem* item = new YGraphicsTipItem;
        qGraphicsItem = item;
        currentItem = item;
        item->setPos(pos);
        item->edit->setFont(tools->getFont());
        // memo by liq 13
        // 此处color为panel的颜色，未使用，代码中直接写死为red
        item->panel->color = tools->getColor();
        // add by liq 13
        // 由于tip的panel为透明，此处改变颜色会崩溃，暂且还原，只用白色字体
//        QColor color = tools->getColor();
//        item->edit->setStyleSheet(QString("color:rgb(%1,%2,%3);background-color:rgba(0,0,0,0);border:none;")
//                                  .arg(color.red()).arg(color.green()).arg(color.blue()));
        item->resize();
        item->setPos(pos);
        item->edit->setFocus();
        item->currentColor = item->panel->color;
        item->currentSize = item->edit->fontInfo().pointSize();
        item->currentFontIsBold = item->edit->fontInfo().bold();
    };break;
    default:return;
    }
    currentItem->startPos = pos;
    scene->addItem(qGraphicsItem);
//    items.append(qGraphicsItem);

    // undo/redo
    QUndoCommand *addCommand = new AddCommand(qGraphicsItem, scene);
    m_undoStack->push(addCommand);
}

bool YImageDrawer::eventFilter(QObject *object, QEvent *event)
{
    QMouseEvent *mouseEvent = reinterpret_cast<QMouseEvent*>(event);
    QKeyEvent *keyEvent = reinterpret_cast<QKeyEvent*>(event);
    // modify by liq 13
//    if(event->type() == QEvent::MouseButtonPress){
    if(event->type() == QEvent::KeyPress){
        if(keyEvent->key() == Qt::Key_Shift){
            // 用于压下shift时，画正方形、圆形、垂直/水平箭头
            shiftKeyPressed = true;
        }
    }else if(event->type() == QEvent::KeyRelease){
        if(keyEvent->key() == Qt::Key_Shift){
            // 用于压下shift时，画正方形、圆形、垂直/水平箭头
            shiftKeyPressed = false;
        }
    }
    if(event->type() == QEvent::MouseButtonPress && mouseEvent->button() == Qt::LeftButton){
        if(!scene->property("OccupyFocus").toBool()){
            pressed = true;
            startPos = mouseEvent->pos();

            if(scene->focusItem() != nullptr){
                YGraphicsItem* yitem = dynamic_cast<YGraphicsItem*>(scene->focusItem());
                if(yitem != nullptr){
                    if(yitem->itemType == Rect || yitem->itemType == Ellipse || yitem->itemType == Arrow){
                        // 点击时保存原size
                        yitem->oldWidth = scene->focusItem()->boundingRect().width();
                        yitem->oldHeight = scene->focusItem()->boundingRect().height();
                        if(yitem->itemType == Rect){
                            yitem->oldPos = scene->focusItem()->pos();
                            yitem->oldLastPos = yitem->lastPos;
                            QGraphicsRectItem* rectItem = dynamic_cast<QGraphicsRectItem*>(scene->focusItem());
                            yitem->oldRect = rectItem->rect();
                        }else if(yitem->itemType == Ellipse){
                            yitem->oldPos = scene->focusItem()->pos();
                            yitem->oldLastPos = yitem->lastPos;
                            QGraphicsEllipseItem* ellipseItem = dynamic_cast<QGraphicsEllipseItem*>(scene->focusItem());
                            yitem->oldRect = ellipseItem->rect();
                        }else if(yitem->itemType == Arrow){
                            yitem->oldPos = scene->focusItem()->pos();
                            yitem->oldLastPos = yitem->lastPos;
                        }
                    }
                }
            }
        }
        // add by liq 13
        if(type == Mosaic && pressed){
            mosaic = new YGraphicsMosaicItem(image);
            // 放在此处才能实时显示
            scene->addItem(mosaic);
            mosaic->setVague(tools->getVague());
            mosaic->setThickness(tools->getThickness());
            mosaic->m_points.append(QPoint(mouseEvent->x(), mouseEvent->y()));

            // undo/redo
            QUndoCommand *addCommand = new AddCommand(mosaic, scene);
            m_undoStack->push(addCommand);
        }
        // add by liq 12
        // 防止绘图过程中操作工具栏再返回绘图时工具栏不显示，需要raise操作
        // liqaddtest
        emit sigDrawToolsReshow();

    }else if(event->type() == QEvent::MouseMove){
        // add by liq 12
        // 防止绘图过程中操作工具栏再返回绘图时工具栏不显示，需要raise操作
        // liqaddtest
        emit sigDrawToolsReshow();

        // add by liq 12
//        if(pressed){
//            emit sigIsDrawing(true);
//        }

        if(type < Text) {
            if(type == Mosaic && pressed){
// liqtest0617 无影响
                // modify by liq 13
//                mosaic->rerect(mouseEvent->pos());
                mosaic->m_points.append(QPoint(mouseEvent->x(), mouseEvent->y()));

            }else if(pressed && !scene->property("inChangeArea").toBool()){
                if(!currentItem){
                    if(startPos != mouseEvent->pos()){
                        createItem(startPos, shiftKeyPressed || globalShiftKeyPressed);
                    }
                }
                if(currentItem){
                    currentItem->rerect(mouseEvent->pos());
                }
            }
        }
    }else if(event->type() == QEvent::MouseButtonRelease){
        if(pressed && type >= Text && !scene->property("inChangeArea").toBool()){
            createItem(startPos, shiftKeyPressed || globalShiftKeyPressed);
        }
        else if(pressed && mouseEvent->button() == Qt::LeftButton && scene->property("inChangeArea").toBool()){
            // Arrow时scene->focusItem()为null，所以使用scene->selectedItems()
            if(scene->selectedItems().size() > 0 && scene->selectedItems().first() != nullptr){
                selectedGraphicsitem = dynamic_cast<QGraphicsItem*>(scene->selectedItems().first());
                if(selectedGraphicsitem != nullptr){
                    YGraphicsItem* yitem = dynamic_cast<YGraphicsItem*>(selectedGraphicsitem);
                    // 鼠标抬起，resize时记录undo/redo
                    if(yitem->itemType == Rect){
//                        if (yitem->oldPos != selectedGraphicsitem->pos() || yitem->oldWidth != selectedGraphicsitem->boundingRect().width() || yitem->oldHeight != selectedGraphicsitem->boundingRect().height()){
                        if (yitem->oldWidth != selectedGraphicsitem->boundingRect().width() || yitem->oldHeight != selectedGraphicsitem->boundingRect().height()){
                            onRectItemSizeChanged(selectedGraphicsitem, yitem->oldPos, yitem->oldRect, QSizeF(yitem->oldWidth, yitem->oldHeight));
                        }
                    }else if(yitem->itemType == Ellipse){
//                        if (yitem->oldPos != selectedGraphicsitem->pos() || yitem->oldWidth != selectedGraphicsitem->boundingRect().width() || yitem->oldHeight != selectedGraphicsitem->boundingRect().height()){
                        if (yitem->oldWidth != selectedGraphicsitem->boundingRect().width() || yitem->oldHeight != selectedGraphicsitem->boundingRect().height()){
                            onEllipseItemSizeChanged(selectedGraphicsitem, yitem->oldPos, yitem->oldRect, QSizeF(yitem->oldWidth, yitem->oldHeight));
                        }
                    }else if(yitem->itemType == Arrow){
//                        if (yitem->oldPos != selectedGraphicsitem->pos() || yitem->oldLastPos != yitem->lastPos){
                        if (yitem->oldWidth != selectedGraphicsitem->boundingRect().width() || yitem->oldHeight != selectedGraphicsitem->boundingRect().height()){
                            onArrowItemSizeChanged(selectedGraphicsitem, yitem->oldPos, yitem->oldLastPos);
                        }
                    }
                }
            }
        }
//        // add by liq 13
//        if(type == Mosaic){
//            // 存储用于撤销
//            items.append(mosaic);
//        }
        pressed = false;
        currentItem = nullptr;

        // add by liq 12
//        emit sigIsDrawing(false);
    }else if(event->type() == QEvent::KeyPress){
        if(keyEvent->key() == Qt::Key_Escape){
            emit quitScreenshot();
            return true;
        }
        else if(keyEvent->key() == Qt::Key_Delete){
            QList<QGraphicsItem*> selectedItems = scene->selectedItems();
            bool deletedFlag = false;
            foreach(QGraphicsItem* item, selectedItems)
            {
                YGraphicsItem* itm = dynamic_cast<YGraphicsItem*>(item);
                if(itm->itemType == Text){
//                    scene->focusItem();
                    YGraphicsTextItem* it = dynamic_cast<YGraphicsTextItem*>(item);
                    if(it->textRect->hasFocus()){
                        // undo/redo
                        QUndoCommand *deleteCommand = new DeleteCommand(scene);
                        m_undoStack->push(deleteCommand);

//                        scene->removeItem(item);
                        item->hide();
//                        items.removeOne(item);
//                        delete item;
                        deletedFlag = true;
                    }else{
                        return QWidget::eventFilter(object, event);
                    }
                }else if(itm->itemType == Tip){
                    YGraphicsTipItem* it = dynamic_cast<YGraphicsTipItem*>(item);
                    if(it->panel->hasFocus()){
                        // undo/redo
                        QUndoCommand *deleteCommand = new DeleteCommand(scene);
                        m_undoStack->push(deleteCommand);

//                        scene->removeItem(item);
                        // 由于Tip删除时编号会重新排列，redo/undo时无法恢复，删除改为隐藏
                        it->hide();
//                        items.removeOne(item);
//                        delete item;
                        // 重新设置编号
                        sortTipCount();
                        deletedFlag = true;
                    }else{
                        return QWidget::eventFilter(object, event);
                    }
                }
                else{
                    // undo/redo
                    QUndoCommand *deleteCommand = new DeleteCommand(scene);
                    m_undoStack->push(deleteCommand);

//                    scene->removeItem(item);
                    item->hide();
//                    items.removeOne(item);
//                    delete item;
                    deletedFlag = true;
                }
            }
            // 只有删除时delete键才return true，否则输入文字时无法接收，并且如果删除后不return true会导致崩溃
            if(selectedItems.size() > 0 && deletedFlag){
                // 需要置为false，否则删除后无法再次创建item
                scene->setProperty("inChangeArea", false);

                return true;
            }
        }
    }
    // add by liq 12
    // 防止快速绘图时边框显示不全
    update();
    return QWidget::eventFilter(object, event);
}

// add by liq 12
void YImageDrawer::onChangePinKey(const QString& key){
    PIN_KEY = key;
}

void YImageDrawer::sortTipCount(){
    tipCnt = 0;
//    for(int i = 0; i < items.size(); ++i){
//        QGraphicsItem* item = items[i];
//        YGraphicsItem* itm = dynamic_cast<YGraphicsItem*>(item);
//        if(itm->itemType == Tip){
//            tipCnt++;
//            YGraphicsTipItem* it = dynamic_cast<YGraphicsTipItem*>(item);
//            if(it->panel->self != tipCnt){
//                it->panel->self = tipCnt;
//                it->panel->count = tipCnt;
//            }
//        }
//    }
    const QList<QGraphicsItem*> sceneItems = scene->items(Qt::AscendingOrder);
    foreach(QGraphicsItem* item, sceneItems){
        YGraphicsItem* itm = dynamic_cast<YGraphicsItem*>(item);

        // 必须添加null的判断，可能删除后的itm为null，可能有内存泄露（目前删除改为隐藏，null的判断暂且保留）
        if(itm != nullptr && itm->itemType == Tip && item->isVisible()){
            tipCnt++;
            YGraphicsTipItem* it = dynamic_cast<YGraphicsTipItem*>(item);
            if(it->panel->self != tipCnt){
                it->panel->self = tipCnt;
                it->panel->count = tipCnt;
            }
        }
    }
    // 重新设置后续新增编号值（因为删除了1个，此处不能再加1）
    YGraphicsTipItemPanel::count = tipCnt;
}

void YImageDrawer::updateShiftKeyPressedVal(bool isPressed){
    globalShiftKeyPressed = isPressed;
}

void YImageDrawer::onDoUndoAction(){
    // 编辑区域focus时执行编辑区域的undo/redo，防止外界undo/redo执行
    if(scene->focusItem() != nullptr){
        YGraphicsItem* fcsItem = dynamic_cast<YGraphicsItem*>(scene->focusItem());
        if(fcsItem != nullptr){
            if(fcsItem->itemType == Text){
                YGraphicsTextItem* textItem = dynamic_cast<YGraphicsTextItem*>(fcsItem);
                if(textItem != nullptr && textItem->edit->hasFocus()){
                    return;
                }
            }else{
                YGraphicsTipItem* tipItem = dynamic_cast<YGraphicsTipItem*>(fcsItem);
                if(tipItem != nullptr && tipItem->edit->hasFocus()){
                    return;
                }
            }
        }
    }
    m_undoStack->undo();
//    if(this->scene->focusItem()){
//        YGraphicsItem* item = dynamic_cast<YGraphicsItem*>(this->scene->focusItem());
//        if(item->itemType == Rect || item->itemType == Ellipse || item->itemType == Arrow){
//            item->reChangePos();
//            item->showChange();
//        }
//    }
    sortTipCount();
    UpdateToolSetting();
    this->update();
}

void YImageDrawer::onDoRedoAction(){
    // 编辑区域focus时执行编辑区域的undo/redo，防止外界undo/redo执行
    if(scene->focusItem() != nullptr){
        YGraphicsItem* fcsItem = dynamic_cast<YGraphicsItem*>(scene->focusItem());
        if(fcsItem != nullptr){
            if(fcsItem->itemType == Text){
                YGraphicsTextItem* textItem = dynamic_cast<YGraphicsTextItem*>(fcsItem);
                if(textItem != nullptr && textItem->edit->hasFocus()){
                    return;
                }
            }else{
                YGraphicsTipItem* tipItem = dynamic_cast<YGraphicsTipItem*>(fcsItem);
                if(tipItem != nullptr && tipItem->edit->hasFocus()){
                    return;
                }
            }
        }
    }
    m_undoStack->redo();
//    if(this->scene->focusItem()){
//        YGraphicsItem* item = dynamic_cast<YGraphicsItem*>(this->scene->focusItem());
//        if(item->itemType == Rect || item->itemType == Ellipse || item->itemType == Arrow){
//            item->reChangePos();
//            item->showChange();
//        }
//    }
    sortTipCount();
    UpdateToolSetting();
    this->update();
}

void YImageDrawer::UpdateToolSetting(){
    if(scene->focusItem()){
        YGraphicsItem* fcsItem = dynamic_cast<YGraphicsItem*>(scene->focusItem());
        // 更新主工具栏显示
        if(fcsItem->itemType == Rect || fcsItem->itemType == Ellipse || fcsItem->itemType == Arrow || fcsItem->itemType == Pen || fcsItem->itemType == Text || fcsItem->itemType == Tip){
            emit sigUpdateToolSetting(fcsItem->itemType);
        }
        // 更新工具栏粗细、颜色、字体设置
        if(fcsItem->itemType == Arrow){
            emit sigUpdateThicknessSetting(fcsItem->currentThickness);
            emit sigUpdateColorSetting(fcsItem->currentColor);
        }else if(fcsItem->itemType == Rect || fcsItem->itemType == Ellipse || fcsItem->itemType == Pen){
            emit sigUpdateThicknessSetting(fcsItem->currentThickness / 2);
            emit sigUpdateColorSetting(fcsItem->currentColor);
        }else if(fcsItem->itemType == Text || fcsItem->itemType == Tip){
            emit sigUpdateColorSetting(fcsItem->currentColor);
            if(fcsItem->itemType == Text){
                YGraphicsTextItem* textItem = dynamic_cast<YGraphicsTextItem*>(fcsItem);
                emit sigUpdateFontsizeSetting(textItem->edit->fontInfo().pointSize());
            }else{
                YGraphicsTipItem* tipItem = dynamic_cast<YGraphicsTipItem*>(fcsItem);
                emit sigUpdateFontsizeSetting(tipItem->edit->fontInfo().pointSize());
            }
        }
    }
}

void YImageDrawer::onItemMoved(QGraphicsItem *movedItem, const QPointF &oldPosition, const QPoint &movedLastPos){
    std::function<void()> m_func_ptr_makePath = nullptr;
    std::function<void()> m_func_ptr_showChange = nullptr;
    YGraphicsItem* yitem = dynamic_cast<YGraphicsItem*>(movedItem);
    if(yitem != nullptr){
        if(yitem->itemType == Arrow){
            YGraphicsArrowItem* item = dynamic_cast<YGraphicsArrowItem*>(movedItem);
            m_func_ptr_makePath = item->fun_ptr_makePath;
        }
        QUndoCommand *moveCommand = new MoveCommand(movedItem, oldPosition, movedLastPos, m_func_ptr_makePath, m_func_ptr_showChange);
        m_undoStack->push(moveCommand);
    }
}

void YImageDrawer::onRectItemSizeChanged(QGraphicsItem *sizeChangedItem, const QPointF &oldPos, const QRectF &oldRect, const QSizeF &oldSize){
    std::function<void()> m_func_ptr_reChangePos = nullptr;
    YGraphicsItem* yitem = dynamic_cast<YGraphicsItem*>(sizeChangedItem);
    if(yitem != nullptr){
        if(yitem->itemType == Rect){
            YGraphicsRectItem* item = dynamic_cast<YGraphicsRectItem*>(sizeChangedItem);
            m_func_ptr_reChangePos = item->fun_ptr_reChangePos;
        }
        QUndoCommand *rectSizeChangedCommand = new ChangeRectItemSizeCommand(sizeChangedItem, oldPos, oldRect, oldSize, m_func_ptr_reChangePos);
        m_undoStack->push(rectSizeChangedCommand);
    }
}

void YImageDrawer::onEllipseItemSizeChanged(QGraphicsItem *sizeChangedItem, const QPointF &oldPos, const QRectF &oldRect, const QSizeF &oldSize){
    std::function<void()> m_func_ptr_reChangePos = nullptr;
    YGraphicsItem* yitem = dynamic_cast<YGraphicsItem*>(sizeChangedItem);
    if(yitem != nullptr){
        if(yitem->itemType == Ellipse){
            YGraphicsEllipseItem* item = dynamic_cast<YGraphicsEllipseItem*>(sizeChangedItem);
            m_func_ptr_reChangePos = item->fun_ptr_reChangePos;
        }
        QUndoCommand *ellipseSizeChangedCommand = new ChangeEllipseItemSizeCommand(sizeChangedItem, oldPos, oldRect, oldSize, m_func_ptr_reChangePos);
        m_undoStack->push(ellipseSizeChangedCommand);
    }
}

void YImageDrawer::onArrowItemSizeChanged(QGraphicsItem *sizeChangedItem, const QPointF &oldPos, const QPoint &oldLastPos){
    std::function<void()> m_func_ptr_makePath = nullptr;
//    std::function<void()> m_func_ptr_showChange = nullptr;
    YGraphicsItem* yitem = dynamic_cast<YGraphicsItem*>(sizeChangedItem);
    if(yitem != nullptr){
        if(yitem->itemType == Arrow){
            YGraphicsArrowItem* item = dynamic_cast<YGraphicsArrowItem*>(sizeChangedItem);
            m_func_ptr_makePath = item->fun_ptr_makePath;
        }
        QUndoCommand *arrowSizeChangedCommand = new MoveCommand(sizeChangedItem, oldPos, oldLastPos, m_func_ptr_makePath);
        m_undoStack->push(arrowSizeChangedCommand);
    }
}
